8. 进程控制
0号进程 : 内核进程,交换进程
1号进程: 用户进程,init进程,调用/etc/rc*,进入多用户或者单用户状态,它将领养孤儿进程
2号进程 : 某些系统,是 pagedaemon,负责虚存的请页操作。
zombie 僵尸进程 :进程已死,其父进程未获取终止信息,释放它占用的资源。
fork : 子进程拷贝父进程的数据,堆,栈,文件描述符等,写时拷贝;子进程不继承的有 时间,锁,未觉信号/警告,
write 不带缓存;printf 等标准I/O带缓存;
标准输出 是 行缓存 由 新行符\n刷新; 写到文件 是 全缓存 结束时刷新;
fork 前的 printf, 写到文件时,其缓存内容 将 复制到 子进程(即子进程也会打印);行缓存,则否
使用:like httpd
1)父进程等客户端的请求,子进程处理请求 2)父进程创建一个子进程,子进程执行CGI
vfork : 是用来执行 exec 的,即 上面的用途 2)
所以,vfork s) 它并不将父进程的地址空间完全复制到子进程中, 子进程在调用exec前,在父进程空间中执行, (即会改变父进程中的值)
b) 保证子进程先执行,结束后父进程再执行
C) 子进程退出一般用_exit, 否则会将父进程的标准输入关闭的!
D) vfork 不能写在 其它非main函数f1中,否则,f1先返回子进程,而后继续执行,会修改f1后的程序,导致父进程执行f1时出错!
取得子进程的结束状态
正常结束:通过 exit return 等取得 退出状态
异常结束: wait or waitpid, 由内核 传递 终止状态
wait VS waitpic
wait 有可能阻塞,若无子进程结束;waitpid 有 WNOHANG 控制不阻塞
wait 等的是第一个结束的子进程 ;waitpid 有 控制 等哪个
waitpid 支持 作业控制 ,WUNTRACED ?
wait3 VS wait4
取得终止子进程(非停止)的资源信息,如CPU时间等
竞态条件
程序的结果,取决于父子进程的执行顺序。sleep 并不能保证其执行顺序,wait 父等子结束,子等父结束?定期询问,父的父ID为1
信号实现
管道实现
exec函数
用exec代替的进程,其数据,代码变化,其他不变
参数列表:L: list --》 V: vector --》
e: env环境参数 p: 用文件名作为参数,PATH为路径;---》无P为全路径
无论其调用哪个exec, 最终都调用系统函数 int execve(const charp a t* h n a m e, char *consta rgv [], char *consten vp [] );
更改用户ID
解释器文件
cat /home/ding/dinginterp
#! /home/brian/dldechoarg echoarg1 echoarg2
execl("/home/ding/dinginterp", "dinginterp", "interparg1", 0);
exec执行的不是解释器文件,而是里面的第一行里的解释器
结果为 /home/brian/dldechoarg echoarg1 echoarg2 "/home/ding/dinginterp", "interparg1"
system函数
9. 进程关系
哑终端 RS-232 推荐标准232,即 windows 中的 COM1, COM2, 有9,15针的
init--fork-->子init--exec getty
当用户键入了用户名后,getty就完成了。然后它以类似于下列的方式调用login程序:
execle("/usr/bin/login", "login", "-p", username, (char *) 0, envp);
最后,login进程改变为登录用户的用户I D ( setuid )并调用该用户的登录shell
execl("/bin/sh", "-sh", (char *) 0);
控制台 getty 方式, 此时shell的父进程为 init; 其它终端登录 为 ttymon
网络登录
inetd : 网络超级服务器,它等待大多数的网络连接,其父进程为init
init-->/etc/rc--->inetd--fork(某网络程序 telnetd)--->login,shell ---> 伪终端(服务器)----IP---(客户端) ,
进程组
int setpgid(pid_pt i d, pid_t p g i d);
procl | proc2 & proc3 | proc4 | proc5 通常有shell 的管道线 编组,所以有 3 个进程组:(后台,控制进程)shell组,proc12, proc345
对话期 session
多个进程组的集合,以上3个进程组为一个会话
pid_t setsid(void); 建立一个新的会话,调用者不能是进程组长(fork新的子进程来实现,新来的不可能是组长),可以有终端,调用后无终端
控制终端
终端,即/dev/tty,包括网络登录的伪终端,
如果程序没有控制终端,则打开此设备将失败。
会话期首进程 创建和控制 终端连接,称为 控制进程
前台进程组处理:停止 ctrl+C INT , quit退出 ctrl+\,挂起SIGTSTP ctrl+Z ; 信号0 // 退出shell ctrl+D
控制进程处理:网络断开连接
作业控制
变为后台进程 : ctrl +Z == kill(getpid(), SIGTSTP);
brian@ubuntu:~$ stty tostop //禁止后台输出到前台,fg恢复后工作
后台进程可能收到终端读写时的 SIGTTIN / SIGTTOUT 信号, 停止后台进程,使用int tcsetpgrp(inft i l e d e s, pid_t p g r p i d) ; 设置为前台
SHELL
brian@ubuntu:~$ ps -xj
PPID PID PGID SID TTY TPGID(终端进程组) STAT UID TIME COMMAND
孤儿进程组
非孤儿进程组:该组中有一个成员的父进程,在属于同一个会话期的另一个进程组内
反之:要么其父进程是同组中的,要么 属于不同会话期
孤儿进程组的每个成员会收到,挂断信号SIGHUP,再收到继续信号SIGCONT
unix进程
最新推荐文章于 2019-04-24 21:32:11 发布