在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
man vfork:
SYNOPSIS pid_t vfork(void); DESCRIPTION Linux description vfork() is a special case of clone(2). It is used to create new processes without copying vfork() differs from fork(2) in that the calling thread is suspended until the child ter‐ As with fork(2), the child process created by vfork() inherits copies of various of the Signals sent to the parent arrive after the child releases the parent's memory (i.e., 创建一个新进程的方法只有由某个已存在的进程调用fork()或vfork(),当然某些进程如init等是作为系统启动的一部风而被内核创建的。 一、fork pid_t fork(void); 子进程是父进程的一个拷贝。即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存的方式访问。fork返回后,子进程和父进程都从调用fork函数返回处开始执行。
二、vfork pid_t fork(void); 2. vfork函数调用的用途 三、fork与vfork的区别 四、结束子进程
由于子进程与父进程的运行是无关的,父进程可先于子进程运行,子进程也可先于父进程运行,所以下段程序可以有两种运行结果。 #include<stdio.h> #include<sys/types.h> #include<unistd.h> int global=4; int main() { pid_t pid; int vari=5; printf("before fork\n"); if((pid=fork())==0) { global++; vari--; printf("child changed\n"); } else printf("parent did nog changed\n"); printf("global=%d,vari=%d\n",global,vari); } root@iZ23onhpqvwZ:~/ms/linux/unp/unpMy/tcpcliserv# ./fork1
root@happy src]# ./a.out vfork创建新进程的主要目的在于用exec函数执行另外的程序,实际上,在没调用exec或exit之前子进程的运行中是与父进程共享数据段的。在vfork调用中,子进程先运行,父进程挂起,直到子进程调用exec或exit,在这以后,父子进程的执行顺序不再有限制。
#include<stdio.h> #include<sys/types.h> #include<unistd.h> int global=4; int main() { pid_t pid; int vari=5; printf("before fork\n"); if((pid=vfork())==0) { global++; vari--; printf("child changed\n"); _exit(0); } else printf("parent did nog changed\n"); printf("global=%d,vari=%d\n",global,vari); exit(0); }
root@iZ23onhpqvwZ:~/ms/linux/unp/unpMy/tcpcliserv# ./fork2 (从这里可以看出共享了数据段的。) 参考:http://blog.csdn.net/lingdxuyan/article/details/4996471
vfork 保证子进程先运行,在她调用 exec 或 exit 之后父进程才可能被调度运行。如果在 调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。 #include<unistd.h> #include<stdio.h> int main() { pid_t pid; int count=0; pid=vfork(); count++; printf("count=%d\n",count); //return 0;没有return 0 } ubuntu输出: root@iZ23onhpqvwZ:~/ms/linux/unp/unpMy/tcpcliserv# ./vfork1 有return 0,输出: count=1 ........................ 如果没有_exit(0)的话,子进程没有调用exec或exit,所以父进程是不可能执行的,在子进程调用exec或exit之后父进程才可能被调度运行。 所以我们加上_exit(0);使得子进程退出,父进程执行,这样else后的语句就会被父进程执行,又因在子进程调用exec或exit之前与父进程数据是共享的,所以子进程退出后把父进程的数据段count改成1了,子进程退出后,父进程又执行,最终就将count变成了2, 改成: pid_t pid; int count=0; pid=vfork(); if(pid==0) { count++; _exit(0); } else { count++; } printf("count=%d\n",count); return 0; 网上抄的一段,可以再理解理解:
linux c 下exit(0);与_exit(0);的区别 #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(void) { pid_t pid; if((pid=fork())==-1) { printf("error"); } else if(pid==0) { printf("ok\n"); exit(0); } else { printf("parent process,output begin\n"); printf("hello word"); _exit(0); } } 调试后你会发现没有 hello word exit是退出去先把内存中的数据输出到文件中,而_exit 这个直接退出,消除内存中的数据; printf是标准行输出,遇到“\n”或者是写入的内存满了才会标准输出; 我们可以尝试在hello word 中加入很多i,假设输入2000个吧(关于行输出自行google),再次调试发现,会有 hello 等字符,这就是溢出了。 回到前面,为什么开始没有hello,虽然hello word 在_exit前,但是你查看汇编会发现,他只是讲数据存在内存中。没有讲数据真正输出。当我们把_exit去掉 hello word就能显示了。为什么呢?这个就是编译器自己加的了。
从图中可以看出,_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit 系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是图中的“清理I/O缓冲”。
所需头文件: exit: #include<stdlib.h> _exit: #include<unistd.h> 函数原型:exit: void exit(int status) _exit: void _exit(int status) 函数传入值:status 是一个整型的参数,可以利用这个参数传递进程结束时的状态。一般来说,0表示正常结束;其他的数值表示出现了错误,进程非正常结束。在实际编程时,父进程可以利用wait 系统调用接收子进程的返回值,从而针对不同的情况进行不同的处理 参考:http://blog.csdn.net/lwj103862095/article/details/8640037 atexit()函数 atexit可以注册终止处理程序,ANSI C规定最多可以注册32个终止处理程序。 终止处理程序的调用与注册次序相反 #include <stdlib.h> int atexit(void (*function)(void)); #include <stdio.h> #include <stdlib.h> void exit_fn1(void) { printf("Exit function #1 called\n"); } void exit_fn2(void) { printf("Exit function #2 called\n"); } int main() { atexit(exit_fn1); atexit(exit_fn2); return 0; }
进程的终止方式:
有8种方式使进程终止,其中前5种为正常终止,它们是
1:从 main 返回
2:调用 exit
3:调用 _exit 或 _Exit
4:最后一个线程从其启动例程返回
5:最后一个线程调用pthread_exit
异常终止有3种,它们是
6:调用 abort
7:接到一个信号并终止
8:最后一个线程对取消请求做出响应
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论