《Unix高级环境编程》第八章 进程控制

来源:互联网 发布:护肤品成分查询软件 编辑:程序博客网 时间:2024/05/16 13:41

Process Control

一、 介绍

本章着眼于Unix系统提供的进程控制。包含了新进程的创建、程序的执行、进程的中止。

此外也涉及到进程的各种ID-real(真实),effective(有效),and saved(保存的); user and group IDs—以及它们如何被进程控制原语(primitives)。

Interpreter files(解释器文件) and the system function。也会涉及到。

二、Process indentifiers

1-进程标识符是什么?

每个进程都有唯一的进程ID,是非负整数。

2-有什么用途

  1. 用于表示唯一进程
  2. 为其唯一性,应用程序经常用process IDs作为文件名的一部分,用于产生唯一的文件名。

3-Process 0是shceduler(调度器)被称为swapper

disk上没有该程序,是内核的一部分,作为系统进程。

4-Process 1是init进程

是什么?

永远不会死亡的一般用户进程,而不是kernel里的系统进程。

作用:

是内核在bootstrap结束后调用。在新版本中程序文件存在/sbin/init中。该进程是负责加载UNIX系统,并使系统进入明确的状态,如multiuser。

5-Process 2是pagedaemon

用于在virtural memory system中支持paging

6-获取进程标识符(identifies)的系统调用

getpid等等,链接:http://blog.csdn.net/feather_wch/article/details/50759118

三、 fork Function

7-fork作用:

已经存在的进程通过fork创建新的进程。
链接如下:http://blog.csdn.net/feather_wch

8-父子进程的堆栈和数据空间

  1. 子进程复制了父进程的数据空间,栈,堆。
  2. 共享text segment

9-copy on write(COW)是什么

自从fork经常接着调用exec,当前很多实现不执行完整的父数据,栈,堆的复制。这些区域是父子进程以read-only方式共享的。在需要修改这些区域的时候,kernel会以page进行复制。

10-Linux中clone(2)也能创建新进程

允许调用者控制父子进程共享什么内容

11-fork的特性,所有父进程打开的文件描述符都会复制到子进程中

因为对每个文件描述符都调用了dup
父子进程给每个打开的描述符共享file table entry

12-父子进程的文件结构,共享同样的file offset

figure8.2
父进程等待child完成再进行write操作,在child进行write后更新了file offset。然后父进程的操作会在该offset后进行write

13- fork之后处理描述符的两种情况

  • 父进程wait子进程的完成:父进程不需要做任何事情,子进程操作文件后会自动更新file offset
  • 父子进程各自做各自的事情:fork之后,父子进程关闭其不需要的描述符。

14-子进程继承父进程的属性

  • Real user ID, real group ID, effective user ID, and effective group ID
  • Supplementary group IDs
  • Process group ID
  • Session ID
  • Controlling terminal
  • The set-user-ID and set-group-ID flags
  • Current working directory
  • Root directory
  • File mode creation mask
  • Signal mask and dispositions
  • The close-on-exec flag for any open file descriptors
  • Environment
  • Attached shared memory segments
  • Memory mappings
  • Resource limits

15- 父子进程的不同之处

  • The return values from fork are different.
  • The process IDs are different.
  • The two processes have different parent process IDs: the parent process ID of the child is the parent; the parent process ID of the parent doesn’t change.
  • The child’s tms_utime, tms_stime, tms_cutime, and tms_cstime values are set to 0 (these times are discussed in Section 8.17).
  • File locks set by the parent are not inherited by the child.
  • Pending alarms are cleared for the child.
  • The set of pending signals for the child is set to the empty set.

16- fork的两种用法

  1. 当父进程想复制本身以至于父子能够执行代码的不同区域。如父进程接受socket传来的信息,子进程用于处理。
  2. 进程想执行不同的程序

四、vfork Function

调用方法和返回值与fork一样
链接:http://blog.csdn.net/feather_wch/article/details/50759655

17-vfork和forksemantics(语义)不同

  • fork一样创建新的进程, 但child不引用的地址空间,不会复制到child中去
    ;child简单的在vfork之后调用exec or exit。换句话说,在执行exec或者exit之前,child运行在parent的地址空间。
  • vfork保证child首先执行,直到child调用exec或者exit。调用之后,恢复parent的执行。

五、exit Function

18- 进程正常结束的五种方法

  1. 在main中return
  2. 执行exit
  3. 执行Exit和_exit
  4. 进程最后的线程的开始程序里执行return
  5. 最后的线程执行pthread_exit

19- 进程异常终止的三种方法

  1. 接收到信号
  2. 调用abort,会产生SIGABRT信号
  3. 最后的线程响应取消的请求

20- 注意点

  1. 无论如何中止,kernel都会关闭该进程所有的描述符,并且释放空间。
  2. 三个exit函数,都会将exit状态作为函数的的参数
  3. 对于异常终止的情况,kernel会产生中止的状态(termination status),来表示异常终止的原因
  4. exit status最终会转换为termination status

21- parent如何检查child的termination status?

figure 8.4

22- 如果parent在child之前中止会发生什么?

init进程会成为所有parent进程中止的child进程的父进程。

内核会在某进程中止的时候,查看该进程是不是现存的某些进程的父进程,如果是,则将相应进程的parent process ID 置为 1(init process ID = 1)

23- child在parent之前中止会发生什么?

kernel保存了所有中止进程的小部分信息(processID,中止状态,CPU执行时间),在parent调用waitorwaitpid时可以获得这些信息。如果parent没有调用这些函数,已经中止的子进程处于zombie状态(使用ps可以查看有Z标志的进程)

24- 进程init进程的子进程中止后,会进入zombie状态吗?

不会!init会自动调用wait获取其中止状态

六、wait、waitpid、waitid Functions

当进程中止时,kernel会发送信号SIGCHLD给父进程。这是异步事件—可以在任何时候发送给parent,因此paren可以选择忽略或者提供signal handler进行处理。
链接:http://blog.csdn.net/feather_wch/article/details/50763353

25- wait和waitpid区别

  • wait会阻塞直到子进程中止。waitpid能有option能防止阻塞
  • waitpid不等待第一个中止的childprocess,有相应option控制等待哪个进程

status如果不是NULL指针,返回的状态保存在里面

sys/wait.h 定义了如下macro(宏)查看中止状态
figure 8.4

26- 参数pid的四种value

  1. pid = -1, 等待任何子进程。在这种情况下waitpid等于wait
  2. pid > 0, 等待进程ID等于pid的子进程
  3. pid == 0, 等待任何进程组ID等于调用进程的(process group id)的进程
  4. pid < -1, 等待任何进程组ID(process group id)等于pid绝对值的子进程

27- wait的注意点

  1. 真正的错误是调用者用没子进程
  2. 其余的错误返回是因为signal中断

28- waitpid的注意点

  1. 返回值是中止的子进程的进程ID
  2. 中止状态保存在status指向的参数里。
  3. 产生错误可能是因为指定的进程和进程组不存在,或者不是调用者的子进程

29- waitpid的options参数的作用

figure 8.7

30- waitpid提供了三个wait不具备的特性

  1. waitpid是我们等待一个特定的进程
  2. waitpid提供了无阻塞版本的wait
  3. waitpid使用WUNTRACEDWCONTINUED选项来支持job control

27- waitid特点:

  1. 和waitpid一样允许等待指定的子进程
  2. process IDprocess group ID 使用了分离的参数,而不是像waitpid和wait一样合成为一个参数。

28- waitid参数说明

id参数的含义取决于idtype

idtype如下
figure 8.9

options决定调用者关心那些状态的改变

figure 8.10

infop是结构体siginfo的指针

该结构体包含了在子进程中造成状态改变的信号的详细信息

八、wait3、wait4 Functions

链接:http://blog.csdn.net/feather_wch/article/details/50768127

29- wait3,wait4是什么?

提供了与waitwaitpidwaitid函数唯一不能提供的特性:增加了额外的参数,用于存放中止进程的所有资源的汇总和其所有的子进程

九、Race condition(竞争条件)

30- 进程等待父进程中止的方法

while(getppid() != 1)    sleep(1);

缺点:polling(轮询)会浪费很多CPU时间

避免竞争和轮询的方法

  1. 使用signals
  2. 使用进程间通信IPC(interprocess communication)

十、exec Function

31- exec注意点:

  1. 调用exec的进程会完全被新的程序替代,从新程序的main开始执行
  2. process ID保持保持原来的值,因为没有创建新的进程
  3. exec替换了当前进程的text,data,heap,stacksegments
  4. 如果execlpexecvp通过路径找到的文件不是可执行文件,那么会认为该文件是shell script(脚本)文件,然后将其输入到shell
  5. l代表是list,需要命令行参数是独立的参数,我们将该argumentNULL结尾。
  6. v代表是vector
  7. p表示使用filename参数和PATH环境变量来查找文件
  8. e表示使用environment list

32- fork和exec的区别

fork创建新的进程
exec初始化新的程序

33- process control primitives有哪些

fork,exec,exit,wait

34- close-on-exec

每个文件描述符都有close-on-exec flag,如果该flag被设置,文件描述符通过exec关闭,否则保持开启。

35- open directory streams调用exec后被关闭

因为opendir就调用了fcntl设置了close-on-execflag

36- effective IDs

real IDs保持不变,effective IDs取决于被执行的程序文件的set-user-IDset-group-ID位。如果被设置,effective IDs会变成该程序文件的owner IDs

37- execve是唯一的系统调用

其余函数都是最终执行了该系统调用

十一、改变User IDs and Group IDs

改变ID可能会用到setuid,setgid,setreuid,setregid,seteuid,setegid
链接:http://blog.csdn.net/feather_wch/article/details/50781252

十三、system Function

方便在程序中执行command
链接:

38- system的具体实现内部有哪些系统调用?

forkexecwaitpid

39- 使用system的优势!

相对于直接调用fork和execsystem能够处理error和处理signal

40- 绝对不要在set-user-IDset-group-ID程序里调用system,可以直接使用fork和exec

这样做会产生安全漏洞

十四、Process Accounting

39 是什么?

开启之后,每次进程终止kernel都会将信息写入accounting record,比如:使用了多少CPU time,开始的时间等等。

40 acct用于关闭 process accounting,accton用于开启

十五、User identification

41 getlogin干什么?—用于得到登录名

#include <unistd.h>char * getlogin(void);    // Returns: pointer to string giving login name if OK, NULL on error

十六、Process Time

42 times作用

获取三种时间:wall clock time, user CPU time, and system CPU time

//times - get process times#include <sys/times.h>clock_t times(struct tms *buf);   //Return: elapsed(溜走的) wall clock time in clock ticks if OK, -1 on errorstruct tms {               clock_t tms_utime;  /* user time */               clock_t tms_stime;  /* system time */               clock_t tms_cutime; /* user time of children */               clock_t tms_cstime; /* system time of children */};

43 如何使用

当前进程和子进程的 user/system CPU time 保存在参数的结构体中
wall clock time是返回值。

我们一般使用相对时间,就是当前times()结果 - 以前times()结果,得到相对时间

44 返回值clock_t使用sysconf(_SC_CLK_TCK)(每秒钟ticks数目)来转换为秒数

0 0