fork是什么?克隆当前的进程,然后创建一个子进程。本文分几个验证实例代码,主要是为解决验证一些小问题。
fork之前打开一个文件的测试。
问题:fork之后,父进程关闭文件,子进程是否还可以正常写文件?
#include
#include
#include
#include
#include
#include
#include int main()
{int fd;char buf[100];int count = 0;int pid;fd = open("hello.txt",O_RDWR|O_CREAT,0666);if(fd < 0){perror("open");return -1;}printf("open ok\n");pid = fork();if(pid == -1){perror("fork");exit(-1);}if(pid > 0){printf("parent:pid = %d\n",getpid());close(fd);}else{while(1){sprintf(buf,"count = %d\n",count++);write(fd,buf,strlen(buf));sleep(1);}}while(1)sleep(1);return 0;
}
这个程序得出的结果是,子进程会不停的向文件中写内容,即便父进程关闭了fd。这说明,fork执行以后,子进程继承了父进程的资源。并且继承了文件描述符,子进程与父进程在fork以后,就是两个不同的进程了。
这时,杀死父进程,子进程将被系统进程接管。
杀死子进程呢?子进程将变成僵尸进程。如何处理僵尸进程呢?暂时先不讨论这个问题。
fork之前创建一个线程。
问题:fork之后,子进程是否拥有一个该线程的复制?
测试实例:fork.c
#include
#include
#include
#include
#include
#include
#include
#include void * mythread(void *arg)
{while(1){printf("pid = %d\n",getpid());sleep(1);}return NULL;
}int main()
{int fd;char buf[100];int count = 0;int pid;pthread_t t;fd = open("hello.txt",O_RDWR|O_CREAT,0666);if(fd < 0){perror("open");return -1;}printf("open ok\n");pthread_create(&t,NULL,mythread,NULL);pid = fork();if(pid == -1){perror("fork");exit(-1);}if(pid > 0){printf("parent:pid = %d\n",getpid());close(fd);}else{while(1){sprintf(buf,"count = %d\n",count++);write(fd,buf,strlen(buf));sleep(1);}}while(1)sleep(1);return 0;
}
编译
gcc fork.c -pthread
测试结果:
lkmao@ubuntu:~/01$ ./a.out
open ok
pid = 124353
parent:pid = 124353
child:pid = 124355
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
pid = 124353
执行pstree -p命令:

{a.out}124354,就是创建的线程,它只有一个。
fork之前使用malloc分配内存。fork之后,父进程free这块内存,请问,子进程是否还有该内存的使用权?
一句话:每个进程都拥有,且独立使用4GB的虚拟内存空间。还像是这么说的。
#include
#include
#include
#include
#include
#include
#include
#include void * mythread(void *arg)
{while(1){printf("pid = %d\n",getpid());sleep(1);}return NULL;
}int main()
{int fd;char* buf;int count = 0;int pid;pthread_t t;fd = open("hello.txt",O_RDWR|O_CREAT|O_TRUNC,0666);if(fd < 0){perror("open");return -1;}printf("open ok\n");buf = malloc(100);pthread_create(&t,NULL,mythread,NULL);pid = fork();if(pid == -1){perror("fork");exit(-1);}if(pid > 0){printf("parent:pid = %d\n",getpid());free(buf);close(fd);}else{printf("child:pid = %d\n",getpid());while(1){sprintf(buf,"count = %d\n",count++);write(fd,buf,strlen(buf));sleep(1);}}while(1)sleep(1);return 0;
}
这个测试结果和实例1一样。
这样验证可能还是不太好,从新写验证代码,fork之前对buf赋值 "count = 0",fork之后,父进程修改buf。然后,子进程等待1秒,然后子进程打印buf,思考子进程打印的buf是什么?不用想的看结果吧。
#include
#include
#include
#include
#include
#include
#include
#include int main()
{char* buf;int count = 0;int pid;pthread_t t;buf = malloc(100);sprintf(buf,"count = %d\n",count++);pid = fork();if(pid == -1){perror("fork");exit(-1);}if(pid > 0){printf("buf = %p\n",buf);printf("parent:pid = %d\n",getpid());sprintf(buf,"pid = %d\n",getpid());printf("parent buf:%s\n",buf);}else{sleep(1);printf("buf = %p\n",buf);printf("child:pid = %d\n",getpid());printf("child buf:%s\n",buf);}while(1)sleep(1);return 0;
}
测试结果:虽然父子进程的buf地址相同,但是父子进程的buf中的内容,是完全不同的。这就是为什么说,每个进程的虚拟地址空间独立的原因吧。
lkmao@ubuntu:~/01$ gcc fork.c
lkmao@ubuntu:~/01$ ./a.out
buf = 0xe01010
parent:pid = 126902
parent buf:pid = 126902buf = 0xe01010
child:pid = 126903
child buf:count = 0
暂时想到这几个问题,关于如何处理僵尸进程呢?这个问题,下次研究。