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;
- }
编译,运行,并使用使tail -f hello.txt监控hello.txt文件的内容更新情况。
- lkmao@ubuntu:~/01$ gcc fork.c
- lkmao@ubuntu:~/01$ ./a.out &
- [1] 118547
- lkmao@ubuntu:~/01$ open ok
- parent:pid = 118547
-
- lkmao@ubuntu:~/01$ tail -f hello.txt
- count = 0
- count = 1
- count = 2
- count = 3
- count = 4
- count = 5
- count = 6
- count = 7
- count = 8
- count = 9
- count = 10
- count = 11
- count = 12
- count = 13
- count = 14
- /*实时更新的数据*/
这个程序得出的结果是,即便父进程关闭了fd,子进程也能够会不停的向文件中写内容,这说明,fork执行以后,子进程继承了父进程的资源。包括继承了文件描述符。且子进程中的文件描述符和父进程中的文件描述符是各自独立存在的。
这时,杀死父进程,子进程将被系统进程接管。
杀死子进程呢?子进程将变成僵尸进程。如何处理僵尸进程呢?暂时先不讨论这个问题。
fork之前创建一个线程。
问题:fork之后,子进程是否拥有一个该线程的复制?
- #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 = 126902
-
- buf = 0xe01010
- child:pid = 126903
- child buf:count = 0
-
-
暂时想到这几个问题,关于如何处理僵尸进程呢?这个问题,下次研究。