分享
 
 
 

Linux系统调用跟我学(2)――进程管理

王朝system·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

作者:雷镇

本文介绍了Linux下的进程概念,并着重讲解了与Linux进程管理相关的4个重要系统调用getpid,fork,exit和_exit,辅助一些例程说明了它们的特点和使用方法。

关于进程的一些必要知识

先看一下进程在大学课本里的标准定义:“进程是可并发执行的程序在一个数据集合上的运行过程。”这个定义非常严谨,而且难懂,如果你没有一下子理解这句话,就不妨看看笔者自己的并不严谨的解释。我们大家都知道,硬盘上的一个可执行文件经常被称作程序,在Linux系统中,当一个程序开始执行后,在开始执行到执行完毕退出这段时间里,它在内存中的部分就被称作一个进程。

当然,这个解释并不完善,但好处是容易理解,在以下的文章中,我们将会对进程作一些更全面的认识。

Linux进程简介

Linux是一个多任务的操作系统,也就是说,在同一个时间内,可以有多个进程同时执行。如果读者对计算机硬件体系有一定了解的话,会知道我们大家常用的单CPU计算机实际上在一个时间片断内只能执行一条指令,那么Linux是如何实现多进程同时执行的呢?原来Linux使用了一种称为“进程调度(process scheduling)”的手段,首先,为每个进程指派一定的运行时间,这个时间通常很短,短到以毫秒为单位,然后依照某种规则,从众多进程中挑选一个投入运行,其他的进程暂时等待,当正在运行的那个进程时间耗尽,或执行完毕退出,或因某种原因暂停,Linux就会重新进行调度,挑选下一个进程投入运行。因为每个进程占用的时间片都很短,在我们使用者的角度来看,就好像多个进程同时运行一样了。

在Linux中,每个进程在创建时都会被分配一个数据结构,称为进程控制块(Process Control Block,简称PCB)。PCB中包含了很多重要的信息,供系统调度和进程本身执行使用,其中最重要的莫过于进程ID(process ID)了,进程ID也被称作进程标识符,是一个非负的整数,在Linux操作系统中唯一地标志一个进程,在我们最常使用的I386架构(即PC使用的架构)上,一个非负的整数的变化范围是0-32767,这也是我们所有可能取到的进程ID。其实从进程ID的名字就可以看出,它就是进程的身份证号码,每个人的身份证号码都不会相同,每个进程的进程ID也不会相同。

一个或多个进程可以合起来构成一个进程组(process group),一个或多个进程组可以合起来构成一个会话(session)。这样我们就有了对进程进行批量操作的能力,比如通过向某个进程组发送信号来实现向该组中的每个进程发送信号。

最后,让我们通过ps命令亲眼看一看自己的系统中目前有多少进程在运行:

$ps -aux(以下是在我的计算机上的运行结果,你的结果很可能与这不同。)

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root 1 0.1 0.4 1412 520 ? S May15 0:04 init [3]

root 2 0.0 0.0 0 0 ? SW May15 0:00 [keventd]

root 3 0.0 0.0 0 0 ? SW May15 0:00 [kapm-idled]

root 4 0.0 0.0 0 0 ? SWN May15 0:00 [ksoftirqd_CPU0]

root 5 0.0 0.0 0 0 ? SW May15 0:00 [kswapd]

root 6 0.0 0.0 0 0 ? SW May15 0:00 [kreclaimd]

root 7 0.0 0.0 0 0 ? SW May15 0:00 [bdflush]

root 8 0.0 0.0 0 0 ? SW May15 0:00 [kupdated]

root 9 0.0 0.0 0 0 ? SW

root 13 0.0 0.0 0 0 ? SW May15 0:00 [kjournald]

root 132 0.0 0.0 0 0 ? SW May15 0:00 [kjournald]

root 673 0.0 0.4 1472 592 ? S May15 0:00 syslogd -m 0

root 678 0.0 0.8 2084 1116 ? S May15 0:00 klogd -2

rpc 698 0.0 0.4 1552 588 ? S May15 0:00 portmap

rpcuser 726 0.0 0.6 1596 764 ? S May15 0:00 rpc.statd

root 839 0.0 0.4 1396 524 ? S May15 0:00 /usr/sbin/apmd -p

root 908 0.0 0.7 2264 1000 ? S May15 0:00 xinetd -stayalive

root 948 0.0 1.5 5296 1984 ? S May15 0:00 sendmail: accepti

root 967 0.0 0.3 1440 484 ? S May15 0:00 gpm -t ps/2 -m /d

wnn 987 0.0 2.7 4732 3440 ? S May15 0:00 /usr/bin/cserver

root 1005 0.0 0.5 1584 660 ? S May15 0:00 crond

wnn 1025 0.0 1.9 3720 2488 ? S May15 0:00 /usr/bin/tserver

xfs 1079 0.0 2.5 4592 3216 ? S May15 0:00 xfs -droppriv -da

daemon 1115 0.0 0.4 1444 568 ? S May15 0:00 /usr/sbin/atd

root 1130 0.0 0.3 1384 448 tty1 S May15 0:00 /sbin/mingetty tt

root 1131 0.0 0.3 1384 448 tty2 S May15 0:00 /sbin/mingetty tt

root 1132 0.0 0.3 1384 448 tty3 S May15 0:00 /sbin/mingetty tt

root 1133 0.0 0.3 1384 448 tty4 S May15 0:00 /sbin/mingetty tt

root 1134 0.0 0.3 1384 448 tty5 S May15 0:00 /sbin/mingetty tt

root 1135 0.0 0.3 1384 448 tty6 S May15 0:00 /sbin/mingetty tt

root 8769 0.0 0.6 1744 812 ? S 00:08 0:00 in.telnetd: 192.1

root 8770 0.0 0.9 2336 1184 pts/0 S 00:08 0:00 login -- lei

lei 8771 0.1 0.9 2432 1264 pts/0 S 00:08 0:00 -bash

lei 8809 0.0 0.6 2764 808 pts/0 R 00:09 0:00 ps -aux

以上除标题外,每一行都代表一个进程。在各列中,PID一列代表了各进程的进程ID,COMMAND一列代表了进程的名称或在Shell中调用的命令行,对其他列的具体含义,我就不再作解释,有兴趣的读者可以去参考相关书籍。

getpid

在2.4.4版内核中,getpid是第20号系统调用,其在Linux函数库中的原型是:

#include /* 提供类型pid_t的定义 */

#include /* 提供函数的定义 */

pid_t getpid(void);

getpid的作用很简单,就是返回当前进程的进程ID,请大家看以下的例子:

/* getpid_test.c */

#include

main()

{

printf("The current process ID is %d

",getpid());

}

细心的读者可能注意到了,这个程序的定义里并没有包含头文件sys/types.h,这是因为我们在程序中没有用到pid_t类型,pid_t类型即为进程ID的类型。事实上,在i386架构上(就是我们一般PC计算机的架构),pid_t类型是和int类型完全兼容的,我们可以用处理整形数的方法去处理pid_t类型的数据,比如,用"%d"把它打印出来。

编译并运行程序getpid_test.c:

$gcc getpid_test.c -o getpid_test

$./getpid_test

The current process ID is 1980

(你自己的运行结果很可能与这个数字不一样,这是很正常的。)

再运行一遍:

$./getpid_test

The current process ID is 1981

正如我们所见,尽管是同一个应用程序,每一次运行的时候,所分配的进程标识符都不相同。

fork

在2.4.4版内核中,fork是第2号系统调用,其在Linux函数库中的原型是:

#include /* 提供类型pid_t的定义 */

#include /* 提供函数的定义 */

pid_t fork(void);

只看fork的名字,可能难得有几个人可以猜到它是做什么用的。fork系统调用的作用是复制一个进程。当一个进程调用它,完成后就出现两个几乎一模一样的进程,我们也由此得到了一个新进程。据说fork的名字就是来源于这个与叉子的形状颇有几分相似的工作流程。

在Linux中,创造新进程的方法只有一个,就是我们正在介绍的fork。其他一些库函数,如system(),看起来似乎它们也能创建新的进程,如果能看一下它们的源码就会明白,它们实际上也在内部调用了fork。包括我们在命令行下运行应用程序,新的进程也是由shell调用fork制造出来的。fork有一些很有意思的特征,下面就让我们通过一个小程序来对它有更多的了解。

/* fork_test.c */

#include

#inlcude

main()

{

pid_t pid;

/*此时仅有一个进程*/

pid=fork();

/*此时已经有两个进程在同时运行*/

if(pid

printf("error in fork!");

else if(pid==0)

printf("I am the child process, my process ID is %d

",getpid());

else

printf("I am th

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有