Linux C 系统编程之进程初探
前置知识
进程
进程是正在运行的程序的示例。当我们运行放在磁盘中的程序时,就产生了进程。不同于程序,进程是一个动态的概念。一个进程不仅包含了程序执行的代码,还包含了程序执行过程中产生的数据、打开的文件、堆、栈等。
程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。 ——摘自百度百科
操作系统管理进程
实际上,一个单核CPU在同一个时刻只能执行一条指令。为了实现“同时”运行多个程序的效果,操作系统采取的方法是:使用一些算法,让CPU在不同的进程切换,使得各个进程在一段时间内都能使用CPU。由于CPU在不同的进程中切换很快,所以用户不易察觉出来,给用户产生一种“同时”运行多个程序的假象。
在李治军老师的操作系统课上有一个很恰当的比喻。
假如你现在在看小说,这时候有人在敲门。你放下书本去开门,然后回来继续看书。在回来继续看书之前,在你的脑中会恢复成之前小说中的场景,然后继续阅读。
下面介绍一下PCB。
PCB(Process Control Block 进程控制单元)
PCB记录着程序运行中的一些信息。结合上面的例子,假如看小说是一个程序,这个程序开始运行, 产生进程。在看小说的过程中,会在你的脑海里产生出小说故事中的一些场景。当你转而去做其他事情后在回来继续看小说时(从其他进程切换过来),你需要将之前的场景恢复,并且事先知道我之前看到了哪一个段落,现在我要从之前的进度继续看下去。PCB就记录了这样的信息,方便CPU在切换进程的时候恢复之前执行的状态。
PCB记录的信息有如下,仅作了解:
进程标识符(内部,外部)
处理机的信息(通用寄存器,指令计数器,PSW,用户的栈指针)。
进程调度信息(进程状态,进程的优先级,进程调度所需的其它信息,事件)
进程控制信息(程序的数据的地址,资源清单,进程同步和通信机制,链接指针)
Linux中有关进程的系统调用
fork
fork的作用是根据现有的进程复制出一个新的进程。称调用fork的进程为父进程,新建的进程子进程。子进程是父进程的一个拷贝。父进程和子进程除了进程的id,即pid(用于标识进程的一个编号而已,全局唯一),不同外,其他均相同。
有趣的是,不同于一般的函数。一般的函数调用一次返回一次,fork函数会返回两次。分别在父进程和子进程中各返回一次。在父进程中,fork函数返回子进程的pid;在子进程中,fork函数返回0(如果新建进程失败返回-1)。 请看以下代码及结果体会。
int pid = fork();
if (pid == 0)
{
printf("我是子进程\n");
}
else if (pid > 0)
{
printf("我是父进程,子进程的pid=%d\n", pid);
}
else //pid == -1
{
printf("错误\n");
}
输出结果:
我是父进程,子进程的pid=106383
我是子进程
也有可能长这个样子(顺序变了):
我是子进程
我是父进程,子进程的pid=106383
由于调用fork之后,有了两个进程,这两个进程都会继续执行下去。前面说道,CPU是在不同进程中切换着运行,所以顺序如何要看操作系统怎么是怎么调度CPU的。也许第一次运行是前者这种情况,第二次运行就变成了后者这种情况。
未完待续...