进程的创建和退出
(1) fork
函数原型 pid_t fork(void);
头文件:#include <unistd.h>
说明:该函数执行成功之后,将会产生一个新的子进程,在新的子进程中其返回值为 0,在原来的父进程中其返回值为大于 0 的正整数,该正整数就是子进程的 PID。
程序:
int main(int argc, char **argv)
{
printf("[%d]\n", __LINE__);
pid_t pid = fork();
printf("[%d]\n", __LINE__);
return 0;
}
结果:
首先是执行第一个打印。后来fork产生一个子进程,这时就要执行两次第二次的打印函数,父进程和子进程是并发的,所以他们是随机的。 这里它是先打印父进程,再打印子进程,因为shell和父进程的关系,所以打印父进程之后退出就有了提示语:[email protected]:~$ ,如果是子进程先退出,就不会出现这种情况。下面是父子进程与shell的关系:
从fork函数开始 以后的代码父子共享,就是父进程和子进程都要执行这段代码。(子进程获得父进程数据空间、堆和栈的副本。但是父子进程并不共享这些存储空间,父子进程共享代码段)。
程序:
int a = 100;
int main(int argc, char **argv)
{
int b = 200;
printf("[%d]\n", __LINE__);
int *p = malloc(sizeof(int));
*p = 300;
pid_t pid = fork();
if(pid > 0) // parent
{
sleep(1);
printf("[parent]*a: %d\n", a);
printf("[parent]*b: %d\n", b);
printf("[parent]*p: %d\n", *p);
}
if(pid == 0) // child
{
a = 1000;
b = 2000;
*p = 3000;
printf("[child]a: %d\n", a);
printf("[child]b: %d\n", b);
printf("[child]*p: %d\n", *p);
}
printf("[%d]\n", __LINE__);
return 0;
}
结果:
[child]a: 10000
[child]b: 20000
[child]*p: 30000
[child]a: 100
[child]b: 200
[child]*p: 300
孤儿进程:当一个父进程首先退出的时候,这时子进程就成了孤儿了,它会由系统的孤儿进程组
领养,一个进程它必须要有父进程,因为他死的时候会变成僵尸状态,然后会由父进
程去释放它的资源。
(2)exit和_exit函数
区别就是有没有调用退出处理函数和清理IO缓冲
程序:
void f1(void)
{
printf("[%s] is calling...\n", __FUNCTION__);
}
void f2(void)
{
printf("[%s] is calling...\n", __FUNCTION__);
}
int main(int argc, char **argv)
{
atexit(f1); //通知退出时调用f1函数
atexit(f2);
printf("abcd");
_exit(0); //不会打印f1,f2函数,不打印abcd
exit(0); //打印f1,f2函数输出abcd因为清理缓存
}