
正文
Linux零起点之进程管理----c语言编程
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
进程 (Process)是指操作系统中被加载到内存中的、正在运行的应用程序实例。进程是系统资源分配的基本单元,在其生命周期内会使用系统中的各种资源。进程主要由程序、数据以及进程控制快(PCB)3个部分组成。关于其基本知识和其状态相关的知识就不介绍了。下面来看看进程的创建和操作吧。
当然,Linux系统中创建进程的函数调用很多(如:system()、popen()等等),此处,主要介绍下fork()函数:
/* Clone the calling process, creating an exact copy.
Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process. */
extern __pid_t fork (void) __THROWNL;
用户可以通过Linux系统提供的fork()来创建多个子线程一实现多个不同任务的并发执行。若创建成功,则从子线程返回0,从父线程返回大于0的正整数(即子线程的惟一标识符id),否则返回-1,表示创建失败。
操作系统内核为完成fork()调用执行的有以下操作:(1)为新进程分配一进程表项和进程标识符,操作系统会检查系统是否有足够的资源来建立一个新进程(2)检查同时存在且正在运行的进程数目,若超过预先规定的最大进程数目,fork()系统调用将会失败。(3)拷贝进程表项中的数据,将父进程的当前记录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。(4)子进程继承父进程的所有文件(5)为子进程创建进程上下文(6)执行子进程,虽然父进程和子进程程序完全相同,但每个进程都有自己的程序计数器PC,并根据fork()返回值的不同,执行不同的分支语言。因此,可以确定fork()是通过复制当前进程来创建新进程的。
#include<stdio.h>
#include<unistd.h>
int main()
{
int pid;
pid=fork();
while(pid==-);//创建子进程直到成功为止
if(pid)
{
printf("子进程\n");
sleep(); }
else
{
printf("父进程\n");
sleep();
}return ;
}
程序运行结果:子进程 或者 父进程
父进程 子进程
从进程并发执行来看,2种情况都有可能,因为父子进程没有同步机制,所以父进程与子进程的输出内容会叠加在一起,输出次序带有随机性。
下面我们继续对Linux中父子进程对程序的共享与私有部分
(1)父进程创建子进程后,父子进程各自分支中的部分规个自私有,其余部分(包括创建前和分支结束后的程序段)都为父子进程共享。先面看个例子:
#include<stdio.h>
#include<unistd.h>
int main()
{
int p;
putchar('X');
while((p=fork())==-);
if(p==)
{
putchar('B');
}
else
putchar('A');
putchar('Y');
return ;
}
运行结果:XAYXBY或XBYXAY
(2)如果子进程在其分支结束处使用exit()系统调用来终止自身的执行,则不会在共享其后的程序段。
(3)对于父子进程不共享的程序段,它们都有各自不同的进程映像,在自己的私有存储空间对数据进行修改不会影响到对方。
#include<stdio.h>
#include<unistd.h>
int main()
{
int p;
int x=;
while((p=fork())==-);
if(p==)
{
x=;
printf("child:x=%d\n",x);
}
else
printf("parent:x=%d\n",x);
return ;
}
运行结果:child:x=9
parent:x=1
Linux进程树
如果一个程序中使用了多个fork()调用,而且每次都不对返回值加以判断,不分析父子进程各自的程序空间,则后面的fork()调用为父子进程所共享,即父子进程返回时都会执行,从而使得家族的进程关系变得复杂。
#include<stdio.h>
#include<unistd.h>
int main()
{
fork();
fork();
fork();
putchar('A');
return ;
}
运行结果:AAAAAAAA
家族树图稍后上传。。
先面我们在进一步看fork()&&fork()||fork():
此处涉及到逻辑运算符运行的机制和对fork()的更深层次了解与认识。其实此式新创建进程4个,下面来分析下:
A&&B 如果A=0,则就没必要执行B了,如果A!=0,则就执行B;
A||B 如果A=0则就执行B,如果A!=0则就不用执行B了。

由此可见fork()&&fork()||fork()创建了4新进程,同理,类此问题迎刃而解。。。






