fork - create a child process (fork函数创建子进程)
#include <unistd.h> pid_t fork(void); /*RETURN VALUE On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.*/
使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(int arg,char *argc[]) { int num=10; pid_t pid; pid=fork(); if(pid==0) { num++; printf("child process running,the num is %d\n",num); printf("pid is %d\n",getpid()); } else if(pid>0) { num++; printf("parent process running,the num is %d\n",num); printf("pid is %d,pid_t 返回值为%d\n",getpid(),pid); } return 0; }
写时复制copy on write
如果多个进程要读取它们自己的那部分资源的副本,那么复制是不必要的。
每个进程只要保存一个指向这个资源的指针就可以了。
如果一个进程要修改自己的那份资源的“副本”,那么就会复制那份资源。这就是写时复制的含义。
孤儿进程和僵尸进程
如果父进程先退出,子进程还没退出,则子进程被称为孤儿进程,如果父亲进程先结束,子进程会托孤给1号init进程。(注:任何一个进程都必须有父进程)
如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。
fork父子进程共享文件
#include<stdio.h> #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(int argv,char *agrc[]) { pid_t pid; int fd; fd = open("local.txt", O_WRONLY); pid = fork(); if (pid == 0) { printf("this is child pid:%d ppid:%d \n", getpid(), getppid()); write(fd, "child\n", 6); } else if (pid > 0) { printf("this is parent pid:%d ppid:%d \n", getpid(), getppid()); write(fd, "parent\n", 7); } close(fd); return 0; }
这种共享文件的方式使父子进程对同一文件使用了一个文件位移量。对于以下情况:一个进程fork了一个子进程,然后等待子进程终止。假定,作为普通处理的一部分,父、子进程都向标准输出执行写操作。如果父进程使其标准输出重定向(很可能是由shell实现的),那么子进程写到该标准输出时,他将更新与父进程共享的该文件的位移量。在我们所考虑的例子中,当父进程等待子进程时,子进程写到标准输出;而在子进程终止后,父进程也写入到标准输出上,并且知道其输出会添加在子进程所写数据之后。如果父、子进程不共享同一文件位移量,这种形式的交互就很难实现。
fork典型应用场景
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(int arg,char *argc[]) { int i; pid_t pid; for(i=0; i<5; i++) { pid=fork(); if(pid>0) { printf("pid is %d,the pid_t value is %d\n",getpid(),pid); printf("current parent process is done\n"); exit(0); } } return 0; }
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(int arg,char *argc[]) { int i; pid_t pid; for(i=0; i<10; i++) { pid=fork(); if(pid==0) { printf("the num%d child process is running\n",i+1); exit(0); } } return 0; }