getpid和getppid
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
功能:调用进程获取自己的ID号
参数:无
返回值:成功返回调用进程的ID,没有失败。
pid_t getppid(void);
功能:调用进程获取父进程的ID号
参数:无
返回值:成功返回调用进程父进程的ID,没有失败。
使用规则
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid>0)
{
printf("父进程中子进程的ID = %d\n",pid);
printf("父进程中当前调用进程的ID = %d\n",getpid());
}
else if(pid==0)
{
printf("子进程中子进程ID = %d\n",getpid());
printf("子进程中父进程的ID = %d\n",getppid());
}
else
{
perror("fork");
return -1;
}
while(1);
return 0;
}
验证孤儿进程是否有父亲进程的id
孤儿进程的父进程会变成号进程
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid>0)
{
printf("父进程中子进程的ID = %d\n",pid);
printf("父进程中当前调用进程的ID = %d\n",getpid());
exit(0);//成功退出
}
else if(pid==0)
{
usleep(10);
printf("子进程中子进程ID = %d\n",getpid());
printf("子进程中父进程的ID = %d\n",getppid());// 1
}
else
{
perror("fork");
return -1;
}
while(1);
return 0;
}
exit和_exit
#include <stdlib.h>
void exit(int status);
功能:进程退出函数,基于标准库,刷新缓冲区后退出。
参数:进程退出的状态:
EXIT_SUCCESS(0):成功退出
EXIT_FAIURE(1):失败退出:
返回值:无
#include <unistd.h>
void _exit(int status);
功能:进程退出函数,基于系统调用,不刷新缓冲区后退出。
参数:进程退出的状态:
EXIT_SUCCESS(0):成功退出
EXIT_FAIURE(1):失败退出
返回值:无
使用规则
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid>0)
{
printf("元旦快乐");
exit(0);//成功退出刷新缓冲区退出
}
else if(pid==0)
{
printf("端午快乐");
fflush(stdout);//手动刷新缓冲区
_exit(0);//不刷新缓冲区退出
}
else
{
perror("fork");
return -1;
}
while(1);
return 0;
}
wait和waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
功能:阻塞回收子进程的资源。
参数:子进程退出时的状态
返回值:成功回收子进程资源后返回子进程的ID,失败时返回-1.
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:阻塞或者非阻塞回收子进程资源
参数1:
>0:回收特定某个子进程资源
=0:回收当前进程组的所有子进程资源
=-1:回收任意的子进程资源
<-1:回收进程组ID等于pid绝对值的所有子进程资源.
参数2:接收进程退出时的状态一般不接收。
参数3:
0:阻塞回收子进程的资源
WNOHANG:非阻塞回收子进程资源.
返回值:成功返回回收的进程ID,失败返回-1,但是如果参数3是WNOHANG
成功后返回0。
使用规则
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid==0)//子进程
{
sleep(5);//模拟子进程的执行时间
printf("我是子进程我要退出了:%d\n",getpid());
exit(1);//成功退出子进程
}
else if(pid>0)//父进程
{
//wait(NULL);//阻塞回收子进程的资源
//waitpid(-1,NULL,0);//阻塞回收子进程的资源
//waitpid(-1,NULL,WNOHANG);//非阻塞回收
while(waitpid(-1,NULL,WNOHANG)>0);
printf("成功回收了子进程的资源\n");//5秒后显示
}
else
{
perror("fork");
return -1;
}
return 0;
}
验证进程的多任务并发执行
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid==0)//子进程
{
while(1)
{
usleep(1000);
printf("我是子进程:%d\n",getpid());
}
}
else if(pid>0)//父进程
{
while(1)
{
usleep(2000);
printf("我是父进程:%d\n",getpid());
}
}
else
{
perror("fork");
return -1;
}
while(1);
return 0;
}
验证孤儿进程和僵尸进程
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid==0)//子进程
{
while(1)
{
usleep(1000);//CPU: 0.0004
printf("我是子进程:%d\n",getpid());
}
}
else if(pid>0)//父进程
{
sleep(3);//父进程执行3秒后退出,子进程变成,了孤儿进程
exit(0);
}
else
{
perror("fork");
return -1;
}
return 0;
}
子进程退出后子进程修改的数据是否保存
#include <myhead.h>
int main(int argc, const char *argv[])
{
int k = 1000;
pid_t pid = fork();
if(pid==0)//子进程
{
sleep(5);
k+=500;
printf("我是子进程:%d\tk = %d\n",getpid(),k);//k=1500
}
else if(pid>0)//父进程
{
waitpid(-1,NULL,0);//阻塞回收子进程资源
printf("我是父进程,回收完成k = %d\n",k);//k = 1000
}
else
{
perror("fork");
return -1;
}
printf("最后的语句:k = %d\n",k);//子进程执行时k=1500父进程执行时k=1000
return 0;
}
创建守护进程
1、创建一个孤儿进程,并修改孤儿进程的操作目录权限为根目录(对根目录某个文件具有读写权限)。
2、将孤儿进程设置为会话组组长,脱离终端独立运行(该孤儿进程变成守护进程)。
3、更改终端下的umask值,以便于创建的文件具有读写执行的全部权限。
4、在根目录下创建一个日志文件。
5、重定向所有的输入输出出错描述符到该日志文件。
#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
功能:设置调用进程为会话组组长。
参数:无
返回值:成功返回会话组组长的(新的)ID失败返回-1,并置位错误码。
#include <unistd.h>
int chdir(const char *path);
功能:修改调用进程的工作目录。
参数:要更改的工作目录
返回值:成功返回0,失败返回-1,并置位错误码。
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
功能:更改某个目录下的umask值
参数:要更改的umask值
返回值:成功返回旧的umask值,没有失败可言。
创建守护进程
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(pid==0)//1、子进程变成了孤儿进程
{
setsid();//2、设置孤儿进程为会话组组长
chdir("/");//3、更改孤儿进程的权限为根目录
umask(0000);//4、更改终端下的umask值为最小
int fd = open("./mylog.txt",O_CREAT|O_TRUNC|O_RDWR,0777);
if(fd==-1)
{
perror("open");
return -1;
}
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
int i = 0;
while(i<=1000)//模拟日志文件写入信息
{
sleep(1);
printf("i = %d\n",i);//写入日志文件
fflush(stdout);
i++;
}
}
else if(pid>0)
{
exit(0);//父进程退出
}
else
{
perror("fork");
return -1;
}
return 0;
}
验证如何创建3个进程
#include <myhead.h>
int main(int argc, const char *argv[])
{
pid_t pid1 = fork();
if(pid1==0)
{
printf("我是大儿子ID = %d\n",getpid());
while(1);
}
else if(pid1>0)
{
printf("我是父进程ID = %d\n",getpid());
pid_t pid2 = fork();
if(pid2==0)
{
printf("我是二儿子ID =%d\n",getpid());
while(1);
}
while(1);
}
else
{
perror("fork");
return -1;
}
return 0;
}
作业:创建3个进程,子进1程拷贝文件的前一半,子进程2拷贝后一半文件,父进程回收两个子进程资源。
#include <luochen.h>
//1、定义子函数,算出源文件的长度返回给主调函数
//2、定义copy函数,参数3个(源文件,目标文件,源文件长度的一半)
int length_file(const char *p1,const char *p2)//计算文件长度
{
int fd1,fd2;
fd1 = open(p1,O_RDONLY);//只读方式打开源文件
if(fd1==-1)
{
perror("open");
return -1;
}
int len = lseek(fd1,0,SEEK_END);//算出源文件的长度返回给主调函数
fd2 = open(p2,O_WRONLY|O_CREAT|O_TRUNC,0664);//创建打开目标文件
if(fd2==-1)
{
perror("open");
return -1;
}
close(fd1);
close(fd2);
return len;//返回源文件的长度
}
int copy_file(const char *p1,const char *p2,int start,int half)
{
int fd1,fd2;
fd1 = open(p1,O_RDONLY);//只读方式打开源文件
if(fd1==-1)
{
perror("open");
return -1;
}
fd2 = open(p2,O_WRONLY);//只写方式打开目标文件
if(fd2==-1)
{
perror("open");
return -1;
}
lseek(fd1,start,SEEK_SET);
lseek(fd2,start,SEEK_SET);
char buff[100];
int sum=0;
while(1)
{
int res = read(fd1,buff,sizeof(buff));
sum+=res;//累加求连续读取的字节数
if(sum>=half||res==0)//子进程和父进程读取到相应位置都要结束
{
write(fd2,buff,(res-(sum-half)));
break;
}
write(fd2,buff,res);
}
close(fd1);
close(fd2);
return 0;
}
//创建3个进程,子进程1拷贝文件的前一半,子进程2拷贝后一半文件,父进程回收两个子进程资源
int main(int argc, const char *argv[])
{
if(argc !=3)
{
printf("外部传参错误\n");
return -1;
}
int len = length_file(argv[1],argv[2]);
pid_t pid1 = fork();
if(pid1 == 0)
{
copy_file(argv[1],argv[2],0,len/2);
//exit(0);
}
else if(pid1 > 0)
{
pid_t pid2 = fork();
if(pid2 == 0)
{
copy_file(argv[1],argv[2],len/2,len-len/2);
//exit(0);
}
while(waitpid(pid1,NULL,WNOHANG)>0);
while(waitpid(pid2,NULL,WNOHANG)>0);
}
else
{
perror("fork");
return -1;
}
return 0;
}
标签:fork,day29,int,pid,基础,printf,进程,return
From: https://blog.csdn.net/luochen330x/article/details/144433765