Linux 网络编程 -UNIX-进程控制

目录

3.1 进程的控制操作

3.1.1 进程的终止

3.1.2 进程的同步

3.1.3 进程终止的特殊情况

3.1.4 进程控制的实例

3.2 进程的属性

3.2.1 进程标识符

3.2.2 进程的组标识符

3.2.3 进程环境

3.2.4 进程的当前目录

3.2.5 进程的有效标识符

3.2.6 进程的资源

3.2.7 进程的优先级


3.1 进程的控制操作


3.1.1 进程的终止


系统调用 exit()实现进程的终止。exit()在 Linux 系统函数库 stdlib.h 中的函数声明如下:

void exit(int status);


exit()只有一个参数 status,称作进程的退出状态,父进程可以使用它的低 8 位。exit() 的返回值通常用于指出进程所完成任务的成败。如果成功,则返回 0;如果出错,则返回非 0 值。
exit()除了停止进程的运行外,它还有一些其它作用,其中最重要的是,它将关闭所有已打开的文件。如果父进程因执行了 wait()调用而处于睡眠状态,那么子进程执行 exit()会重新启动父进程运行。另外,exit()还将完成一些系统内部的清除工作,例如缓冲区的清除工作等。
除了使用 exit()来终止进程外,当进程运行完其程序到达 main()函数末时,进程会自动终止。当进程在 main()函数内执行一个 return 语句时,它也会终止。
在 Linux 中还有一个用于终止进程的系统调用_exit()。它在 Linux 系统函数库 unistd.h
中被声明:

void _exit(int status)


其使用方法与 exit()完全相同,但是它执行终止进程的动作而没有系统内部的清除工作。因此,只有那些对系统内部了解比较深的程序员才使用它。



3.1.2 进程的同步


系统调用 wait()是实现进程同步的简单手段,它在 Linux 系统函数库 sys/wait.h 中的函数声明如下:

pid_t wait(int *status)


我们在前面已经看到了,当子进程执行时,wait()可以暂停父进程的执行,使起等待。一旦子进程执行完,等待的父进程就会重新执行。如果有多个子进程在执行,那么父进程中的 wait()在第一个子进程结束时返回,恢复父进程执行。
通常情况下,父进程调用 fork()后要调用 wait()。例如:

 pid=fork();
if (!pid){
/* 子进程 */
} else {
/* 父进程 */ wait(NULL);
}


当希望子进程通过 exec 运行一个完全不同的进程时,就要进程fork()和wait()的联用。wait()的返回值通常是结束的那个子进程的进程标识符。如果 wait()返回-1,表示没有子进程结束,这时 errno 中含有出错代码 ECHILD。
wait()有一个参数,它可以是一个指向整型数的指针,也可以是一个 null 指针。如果参数用了 null 指针,wait 就忽略它。如果参数是一个有效的指针,那么 wait 返回时,该指针就指向子进程退出时的状态信息。通常,该信息就是子进程通过 exit 传送出来的出口信息。下面的程序 status 就给出了这种情况下,wait 的使用方法。

#include <stdio.h> #include <unistd.h> #include <sys/wait.h>
 
main()
{
int pid,status,exit_status;
 
if ((pid=fork()) <0)
{
perror("fork failed"); exit(1);
}
 
if (!pid)
/* 子进程 */ sleep(4);
exit(5); /* 使用非零值退出,以便主进程观察 */

 
}
 
/* 父进程 */
if (wait(&status) <0) { perror("wait failed"); exit(1);
}
 
/* 将 status 与 0xFF(255)与来测试低 8 位 */ if (status & 0xFF)
printf("Somne low-roderbits not zero\n"); else {
exit_status=status >> 8; exit_status &=0xFF;
printf("Exit status from %d was %d\n", pid,exit_status);
}
exit(0);
}


虽然这个过程看起来有一点复杂,但是其含义十分清除:通过 exit 返回给父进程之值存放在 exit_status 的低位中,为了使其有意义,exit_status 的高 8 位必须为 0(注意,在整型量中,低 8 位在前,高 8 位在后)。因此从 wait()返回后,就可以用按位与操作进行测试, 如果它们不为 0,表示该子进程是被另一个进程用一种称为信号的通信机构停止的,而不是通过 exit()结束的。



3.1.3 进程终止的特殊情况


我们在前面讨论了用 wait()和 exit()联用来等待子进程终止的情况。但是,还有两种进程终止情况值得讨论。这两种情况为:
1. 子进程终止时,父进程并不正在执行 wait()调用。
2. 当子进程尚未终止时,父进程却终止了。
在第一种情况中,要终止的进程就处于一种过渡状态(称为 zombie ),处于这种状态的进程不使用任何内核资源,但是要占用内核中的进程处理表那的一项。当其父进程执行wait()等待子进程时,它会进入睡眠状态,然后把这种处于过渡状态的进程从系统内删除, 父进程仍将能得到该子进程的结束状态。
在第二种情况中,一般允许父进程结束,并把它的子进程(包括处于过渡状态的进程)
交归系统的初始化进程所属。



3.1.4 进程控制的实例


在这一部分,我们将利用前面介绍的进程控制的知识,来构造一个简单的命令处理程序,取名为 smallsh。这样作有两个目的:第一,可以巩固和发展我们在这一章中介绍的概念;第二,它展示了标准的 Linux 系统程序也没 有什么特别的东西。特别是,它表明了 shell 也只是一个在用户注册时调用的普通程序。
smallsh 的基本功能是:它能在前台或后台接收命令并执行它们。它还能处理由若干个命令组成的命令行。它还具有文件名扩展和 I/O 重定向等功能。
smallsh 的基本逻辑如下:

while (EOF not typed) {
从用户终端取得命令行执行命令行
}


我们把取命令行内容用一个函数来完成,并取名为 userin。userin 能显示提示符,然后等待用户从键盘输入一命令行信息。它接收到的输入内容应存入程序的一个缓冲区中。
我们可以忽略到一些初始化工作,但是,userin 的基本步骤是:首先显示提示符,提示符的具体内容由用户通过参数传送给函数;然后每次从键盘读一个字符,当遇到换行符或文件结束符(用 EOF 符号表示)时,就结束。
我们用的基本输入例程是 getchar,它实际上是标准 I/O 库中的一个宏(macro),它从程序的标准输入读入一个字符,userin 把每个读入的字符都存入字符型数组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值