
进程处理机制

进程属性
 
标识符
 
进程状态
通常进程的状态被划分为五种:初始态、 就绪态、运行态、睡眠态 和终止态。初始态一般不进行讨论,因为当初始化完成后,进程会立刻转化为就绪态。 ①就绪态 处于就绪态(Ready)的进程,所需的其它资源已分配到位,此时只等待cpu,当可以使用cpu时,进程会立刻变为运行态。 ②运行态 进程处于运行态(Execting)时会占用cpu,处于此状态的进程的数目必定小于等于处理器的数目,即每个cpu上至多能运行一个进程。 ③睡眠态 处于睡眼态(Sleeping)的进程会因某种原因而暂时不能占有cpu。睡眠态分为不可中断的睡眠和可中断的睡眠 ④终止态 处于终止态的进程已运行完毕,此时进程不会被调度,也不会再占用CPU。  
寄存器信息

页表指针
  
进程组和会话
 
进程控制

fork 创建进程
    案例1:使用fork()函数创建一个进程,进程创建成功后使父进程与子进程分别执行不同的功能
int main()
{
pid_t pid;
pid = fork(); //调用fork()函数创建子进程
if (pid == -1) //创建失败
{
perror("fork error");
exit(1); //退出进程,指定返回值1
}
else if (pid > 0) //父进程
{
printf("parent process,pid=%d,ppid=%d\n", getpid(), getppid());
}
else if (pid == 0) //子进程
{
printf("child process,pid=%d,ppid=%d\n", getpid(), getppid());
}
printf("........finish..........\n");
return 0;
}
 案例2:创建多个进程 for循环      
int main()
{
pid_t pid;
int i;
for (i = 0; i<5; i++){ //循环创建进程
if ((pid = fork()) == 0) //若当前进程为子进程,便跳出循环
break;
}
if (pid == -1){
perror("fork error");
exit(1);
}
else if (pid>0){ //父进程
printf("parent process:pid=%d\n", getpid());
}
else if (pid == 0){ //子进程
printf("I am child=%d,pid=%d\n", i + 1, getpid());
}
return 0;
}
 顺序不递增?   
int main()
{
pid_t pid;
int i;
for(i=0;i<5;i++){
if((pid=fork())==0)
break;
}
if(pid==-1){
perror("fork error");
exit(1);
}
else if(pid>0){
sleep(5);
printf("parent pid=%d\n",getpid());
}
else if(pid==0){
sleep(i);
printf("I am child%d pid=%d\n",i+1,getpid());
}
return 0;
}


数据共享机制
 
exec函数
    案例6-3:在程序中创建一个子进程,之后使父进程打印自己的pid信息,使子进程通过exec函数族获取系统命令文件,执行ls命令。
int main()
{
pid_t pid;
pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}
else if (pid > 0)
{
printf("parent process:pid=%d\n", getpid());
}
else if (pid == 0)
{
printf("child process:pid=%d\n", getpid());
//execl("/bin/ls","-a","-l","test_fork.c",NULL); //①
//execlp("ls","-a","-l","test_fork.c",NULL); //②
char *arg[] = { "-a", "-l", "test_fork.c", NULL }; //③
execvp("ls", arg);
perror("error exec\n");
printf("child process:pid=%d\n", getpid());
}
return 0;
}
 这里查询的是test_fork.c的  
进程退出 exit
   
特殊进程

进程同步
 
wait()函数
 案例6-4:若子进程p1是其父进程p的先决进程,使用wait()函数使进程同步。
int main()
{
pid_t pid, w;
pid = fork();
if (pid == -1){
perror("fork error");
exit(1);
}
else if (pid == 0){
sleep(3);
printf("Child process:pid=%d\n", getpid());
}
else if (pid > 0){
w = wait(NULL);
printf("Catched a child process,pid=%d\n", w);
}
return 0;
}

以上结果在执行程序3秒后输出,因为代码第13行使用sleep()函数使子进程沉睡3秒才执行。观察程序执行情况:子进程在程序执行3秒后完成并输出子进程pid;因为父进程中执行的操作只是回收子进程,所以父进程在子进程终止后立刻输出。由执行情况可知,父进程在子进程结束后才结束,父进程成功捕获了子进程。
当然,wait()函数中的参数可以不为空。若status不为空,wait()函数会获取子进程的退出状态,退出状态被存放在exit()函数参数status的低八位中。使用常规方法读取比较麻烦,因此Linux系统中定义了一组用于判断进程退出状态的宏函数,其中最基础的是WIFEXITED()和WEXITSTATUS(),它们的参数与wait()函数相同,都是一个整型的status。宏函数的功能分别如下: (1)WIFEXITED(status):用于判断子程序是否正常退出,若是,则返回非0值;否则返回0。
(2)WEXITSTATUS(status):WEXITSTATUS()通常与WIFEXITED()结合使用若WIFEXITED返回非0值(即正常退出),则使用该宏可以提取子进程的返回值。
案例6-5:使用wait()函数同步进程,并使用宏获取子进程的返回值。
int main()
{
int status;
pid_t pid, w;
pid = fork();
if (pid == -1){
perror("fork error");
exit(1);
}
else if (pid == 0){
sleep(3);
printf("Child process:pid=%d\n", getpid());
exit(5);
}
else if (pid > 0){
w = wait(&status);
if (WIFEXITED(status)){
printf("Child process pid=%d exit normally.\n", w);
printf("Return Code:%d\n", WEXITSTATUS(status));
}
else
printf("Child process pid=%d exit abnormally.\n", w);
}
return 0;
}

案例6-5的第6行中定义了一个整型变量status,该变量在wait()函数中获取子进程的退出码。之后通过宏WIFEXITED判断返回码是否为0,当不为0时,使用宏WEXITSTATUS将返回码转换为一个整型数据。
waitpid()函数
wait()函数具有一定局限性,若当前进程有多个子进程,那么该函数就无法确保作为先决条件的子进程在父进程之前执行,此时可使用waitpid()函数实现进程同步。
 waitpid()函数比wait()函数多两个参数:pid和options。     案例6-6.使父进程等待进程组中某个指定的进程,若该进程不退出,则让父进程一直阻塞。
int main()
{
pid_t pid, p, w;
pid = fork(); //创建第一个子进程
if (pid == -1){ //第一个子进程创建后父子进程的执行内容
perror("fork1 error");
exit(1);
}
else if (pid == 0){ //子进程沉睡
sleep(5);
printf("First child process:pid=%d\n", getpid());
}
else if (pid > 0){ //父进程继续创建进程
int i;
p = pid;
for (i = 0; i < 3; i++) //由父进程创建3个子进程
{
if ((pid = fork()) == 0)
break;
}
if (pid == -1){ //出错
perror("fork error");
exit(2);
}
else if (pid == 0){ //子进程
printf("Child process:pid=%d\n", getpid());
exit(0);
}
else if (pid > 0){ //父进程
w = waitpid(p, NULL, 0); //等待第一个子进程执行
if (w == p)
printf("Catch a child Process:pid=%d\n", w);
else
printf("waitpid error\n");
}
}
return 0;
}
  案例6-7:使用waitpid)函数不断获取某进程中子进程的状态。
int main()
{
pid_t pid, w;
pid = fork();
if (pid == -1){
perror("fork error");
exit(1);
}
else if (pid == 0){
sleep(3);
printf("Child process:pid=%d\n", getpid());
exit(0);
}
else if (pid > 0){
do{
w = waitpid(pid, NULL, WNOHANG);
if (w == 0){
printf("No child exited\n");
sleep(1);
}
} while (w == 0);
if (w == pid)
printf("Catch a Child process:pid=%d\n", w);
else
printf("waitpid error\n");
}
return 0;
}
 案例6-7的父进程代码中设置了一个循环,在循环中调用waitpid()函数,并使用sleep()函数控制waitpid(),使其每隔1秒捕捉一次子进程信息;同时使子进程沉睡了3秒,因此父进程会输出3次Nochildexited。3秒后子进程终止,waitpid()成功捕获到子进程的退出信息并使父进程继续运行,从而输出捕提到的子进程id。

进程管理命令

ps
   输出信息包含四项:pid:进程的id; TTY表明启动进程的终端; TIME 表示进程到目前为止真正占用CPU的时间 CMD表示启动该进程的命令
  比如ps u  其中USER表示启动进程的用户,pid、TTY、TIME这些选项的含义与ps默认输出的相同,其余各项代表的含义分别如下:
- %CPU表示进程占用CPU的时间与进程已运行时间的百分比,一般情况下这个数值不会达到100%。
- ·%MEM表示进程的物理内存集与系统物理内存的百分比。VSZ表示虚拟内存集,即进程占用虚拟内存的大小(1024字节为一个单位)。
- RSS表示驻留集大小,即进程使用的物理内存的大小(1024字节为一个单位)。
- STAT表示进程当前的状态。D表示不可中断的睡眠态,R表示运行态,S表示可中断的睡眠态,T表示停止,Z表示低死态(即户进程)。状态之后的表示该进程是会话进程中的首进程。
- COMMAND即CMD,表示启动该进程的命令
ps与sys风格如下  其余更多请查询linux系统的man手册
top
ps命令执行后,会显示执行命令那一刻系统中进程的相关信息。若想使信息动态地显示,可以使用命令top。 top命令的格式如下:
tpo -选项
 图中第1行中显示的是top命令的相关信息,其中各项分别表示:系统当前时间为20:35:42:系统到现在已运行8分:系统中当前有1个用户登录:系统1分钟、5分钟、15分钟内的平均负载分别为0.04、0.23、0.21。
第2行显示与进程相关的信息:系统中共有141个进程,其中2个处于运行态,139个处于睡眠态,0个处于停止状态,0个处于死态。
第3行显示与CPU相关的信息,若系统是单核的,则这个信息只有一行: 若系统是双核或多核的,则每个CPU都会有对应的信息。其中各项分别表示:用户占用CPU的百分比为0.0%,系统占用CPU的百分比为0.0%,优先级被更改过的进程占用CPU的百分比为0.0%,空闲CPU的百分比为99.7%,1/O等待占用CPU的百分比为0.0%,硬中断占用CPU的百分比为0.0%,软中断占用CPU的百分比为0.3%,虚拟机被hypervisior(虚拟机监视器)愉去的时间所古的百分比为0.0%,
第4行显示与内存状态相关的信息:系统的物理内存总量为1867024KB.已经使用的内存总量为287724KB,空闲内存总量为1192408KB,缓存的内存量为386892KB
第5行显示swap交换分区的信息:交换区的总容量为2097148KB,已经使用的容量为0KB,空闲容量为2097148KB,缓冲的交换区容量为1378288kb。
以上几行信息的显示可以通过热键1、t、m来分别控制第6行为一个空行,之后黑色背景行为top命令默认显示的输出项。pid等项不再赞述,其余尚未介绍的输出项代表的含义分别如下;
   当使用热键r、k时,第6行会给出相应的提示并等待输人。若要终止进程,在提示信息后输人要操作的进程的pid即可:若要重置优先级,按下热键r,输入pid后,第6行会提示输入nice值。
top的监测界面默认每隔3秒刷新一次,读者可以使用选项d自定义刷新间隔:top显示的内容只有一屏,超出一屏的进程无法查看,若想查看更多进程的状态,可以使用选项-b,该选项使用批处理的模式进行操作,一次显示一屏,3秒滚动一次;若只想观察某段时间内的变化情况,可以使用选项-n来指定循环显示的次数。top的选项还有很多,读者可通过man手册学习更多内容。
pstree

pgrep 选项 [参数]
 
nice
除了top命令 热键r重置优先级 也可以用这个  nice常用的选项为-n,n表示优先级,是一个整数。 nice的参数通常为一个进程名。假设进程top的优先级为0,要修改bash的优先级为5,则可以使用以下命令实现:
nice -n 5 bash
修改后可以用top查看bash 的优先级
nice命令不但能修改已存在进程的优在创建进程的同时,通过设置进程的nice值为进程设定优先级。假设当前top命令的此时选行的命令。优先级已被设置为5,那么再次调用t改其优先级为11,则应使用的命令如下所示:
nice -n 6 top
当更改nice值时,优先级PR和nice值NI都会改变,其变化的规律为:新值=原值+n,n为本次命令中指明的nice值
bg和fg
Linux系统中的命令分为前台命令和后台命令。所谓前台命令,即在命令执行后,命令执行过程中的输出信息会逐条输出到屏幕,或者命令打开的内容(如i打开vim编辑器)会替代原来的终端命令,如压缩解压命令等:所谓后台命令,即命令执行后,不占用命令提示符,用户可继续在终端中输人命令,执行其他操作的命令
bg:
 bg 参数
也可以在命令后追加符号&,在进程创建时直接调入后台执行,其用法如下:
command &
使用快捷键组合Ctrl+Z也能将进程调人后台,但调入后台的进程会被暂时停止
fg:


jobs
    jobs命令的参数为作业号,用于显示某个作业的信息。该命令一般与bg、fg命令配合使用。
##kill
 

|