关于Linux多进程
2013-05-08 23:56
85 查看
今天看了《Linux高级程序设计》中有关进程的部分,在这里仅写一下自己的理解,望大家多多指教。总体感觉跟Windows上的进程不太一样,初次学习时甚至搞不懂程序是怎么运行的,其中最让我不能理解的是父、子进程竟然在一个函数中运行。其中有这样一个例子:
int main(void)
{
pid_t pid = fork();
if (pid == -1)
{
printf("fork error");
}
else if (pid == 0)
{
printf("in the child process");
}
else
{
printf("in the parent process");
}
return 0;
}
在上面的程序中,通过fork函数创建了一个进程,但并没有像Windows程序中通过CreateProcess创建进程那样启动另外一个新的程序,而是在fork后开始有两个进程在运行同一份代码,上面程序只是通过fork的返回值判断该运行父进程还是子进程的代码。之前在Linux的多进程时,就被这一点给弄糊涂了,硬是没搞懂程序是怎么运行的,通过亲手编写代码测试后才真正理解这是怎么一回事。
在fork函数之前,只有一个进程(即父进程)在运行,当调用fork成功后,就会出现新的进程(即子进程)从fork的下一句代码开始执行,而父进程则继续原来的执行,也是fork的下一句代码。fork只是创建的一个进程,无法控制该进程去执行特定的代码,所以在程序中通常通过fork的返回值来判断下一步该执行什么操作。在父进程中,fork将返回新创建的子进程的PID,而在子进程中,这个返回值为0。子进程创建成功后,会复制父进程的几乎所有信息,包括副进程的代码段、数据段、堆、栈以及PCB等信息。我的理解是,栈中在fork函数之前的所有数据在父子进程中都是相同的,从fork开始,即fork的返回值,父子进程就拥有了各自独立的进程空间了。对于一些内核对象的句柄,如打开的文件、SOCKET、管道等,同样会复制到子进程中,而且父子进程中的句柄指向内核中相同的对象,对于文件,它们共享文件指针、偏移、权限等,且在父子进程中需要分别关闭这些句柄。这些特性是在Windows上使用CreateProcess无法做到的。
另外,Linux提供了exec系列的函数,如execl、execp等,它们用来在进程中运行新代码,即运行其他的程序,这一点似乎和Windows的CreateProcess相同。但是,CreateProcess是创建一个新的进程来运行新程序,可以选择等待新进程退出或继续执行本程序代码。而exec系列函数并不创建新进程,而仅仅将新程序的资源加载到内核中并执行新的代码,新程序的代码运行结束后才会回到原有程序继续执行,即exec函数的下一句代码。如果要实现CreateProcess类似的功能,则需要使用fork函数创建一个新进程,然后在子进程中调用exec系列函数执行新的程序。
进程退出后,会自动释放用户控件的所有资源,如执行退出处理函数、刷新流缓冲区等,但是进程内核控件的资源,如PCB,并没有释放,它只能由父进程完成,在父进程中调用wait、waitpid等待所有或指定进程退出,并回收子进程的内核进程资源。如果父进程比子进程早退出,那么子进程的父进程会更改为系统的init进程,它会在子进程退出时回收子进程的内核空间资源。
int main(void)
{
pid_t pid = fork();
if (pid == -1)
{
printf("fork error");
}
else if (pid == 0)
{
printf("in the child process");
}
else
{
printf("in the parent process");
}
return 0;
}
在上面的程序中,通过fork函数创建了一个进程,但并没有像Windows程序中通过CreateProcess创建进程那样启动另外一个新的程序,而是在fork后开始有两个进程在运行同一份代码,上面程序只是通过fork的返回值判断该运行父进程还是子进程的代码。之前在Linux的多进程时,就被这一点给弄糊涂了,硬是没搞懂程序是怎么运行的,通过亲手编写代码测试后才真正理解这是怎么一回事。
在fork函数之前,只有一个进程(即父进程)在运行,当调用fork成功后,就会出现新的进程(即子进程)从fork的下一句代码开始执行,而父进程则继续原来的执行,也是fork的下一句代码。fork只是创建的一个进程,无法控制该进程去执行特定的代码,所以在程序中通常通过fork的返回值来判断下一步该执行什么操作。在父进程中,fork将返回新创建的子进程的PID,而在子进程中,这个返回值为0。子进程创建成功后,会复制父进程的几乎所有信息,包括副进程的代码段、数据段、堆、栈以及PCB等信息。我的理解是,栈中在fork函数之前的所有数据在父子进程中都是相同的,从fork开始,即fork的返回值,父子进程就拥有了各自独立的进程空间了。对于一些内核对象的句柄,如打开的文件、SOCKET、管道等,同样会复制到子进程中,而且父子进程中的句柄指向内核中相同的对象,对于文件,它们共享文件指针、偏移、权限等,且在父子进程中需要分别关闭这些句柄。这些特性是在Windows上使用CreateProcess无法做到的。
另外,Linux提供了exec系列的函数,如execl、execp等,它们用来在进程中运行新代码,即运行其他的程序,这一点似乎和Windows的CreateProcess相同。但是,CreateProcess是创建一个新的进程来运行新程序,可以选择等待新进程退出或继续执行本程序代码。而exec系列函数并不创建新进程,而仅仅将新程序的资源加载到内核中并执行新的代码,新程序的代码运行结束后才会回到原有程序继续执行,即exec函数的下一句代码。如果要实现CreateProcess类似的功能,则需要使用fork函数创建一个新进程,然后在子进程中调用exec系列函数执行新的程序。
进程退出后,会自动释放用户控件的所有资源,如执行退出处理函数、刷新流缓冲区等,但是进程内核控件的资源,如PCB,并没有释放,它只能由父进程完成,在父进程中调用wait、waitpid等待所有或指定进程退出,并回收子进程的内核进程资源。如果父进程比子进程早退出,那么子进程的父进程会更改为系统的init进程,它会在子进程退出时回收子进程的内核空间资源。
相关文章推荐
- Linux下安装oracle关于UnsatisfiedLinkError exception loading native library:njni10报错解决
- 关于LINUX某些驱动程序如GPIO编译的时候提示未定义的问题
- 关于linux系统中close()方法引发一起“血案”
- 关于linux卸载设备时的busy问题处理
- 关于linux中的C语言的 动态链接库
- 关于在Linux下apache-maven的安装
- 关于Linux虚拟化技术KVM的科普 科普四(From humjb_1983)
- linux 使用有关于磁盘命令:
- 关于 linux disable irq
- 关于linux中的iconv转码
- 2017-7-19-每日博客-关于Linux下的CentOS中文件夹基本操作命令.doc
- 关于linux下获取系统当前时间的方法汇总
- 关于linux系统的OOM Killer
- Linux下关于printf 与sleep一起运行的困惑
- 关于Linux无法打开动态链接库.so的解决方法
- linux关于文件分配置权限
- Linux关于watch的用法
- Linux进程关于文件描述符的数量限制
- 关于Hyper-V热迁移中linux出现网络中断的解决方法
- 关于Linux/Unix的Profile文件