目录

进程

记录自己所学的关于进程的所有知识。

进程标识

0号进程为调度进程/交换进程,是内核的一部分。

1init进程由内核调用,读取/etc/rc* /etc/inittab /etc/init.d中的配置后运行,是系统后来所有进程的祖先,是所有孤儿进程的父进程。

pid_t getpid(void);         // 获取当前进程 ID
pid_t getppid(void);        // 获取当前进程的 父进程ID
uid_t getuid(void);         // 当前进程的 用户ID
uid_t geteuid(void);        // 当前进程的 有效用户ID
gid_t getgid(void);         // 当前进程的 组ID
gid_t getegid(void);        // 当前进程的 有效组ID
int   setuid(uid_t uid);    // 改变进程所有者
int   seteuid(uid_t uid);
int   setgid(gid_t gid);
int   setegid(gid_t gid);

创建进程

pid_t fork(void);           // 分叉,创建子进程,返回0;父进程返回 子进程pid

创建子进程后,子进程复制父进程的文件描述符、数据空间、堆和栈,独立出来,共享的只有正文段。fork后,父子进程处于同样起跑线,谁先执行是不确定的。

由于文件描述符是指针,所以父、子进程的文件描述符实际上还是指向同一个文件表,因此子进程对文件描述符的操作会影响到父进程,反过来也一样。所以fork后,为了避免父、子进程相互影响,两者都应该关闭自己不用的文件描述符(删除指针)。

子进程几乎继承了父进程的所有属性(各种用户ID、工作目录、umask、环境),除了文件锁、闹钟、信号集。

fork一般有两种应用,下面分别说明。

网络服务进程

父进程收到到请求后,希望复制自己,通过子进程执行代码段里不同的代码分支,处理请求。而父进程继续等待下一个客户端的请求。

执行不同程序

这是shell的常见情况,fork子进程返回后,立即调用exec加载另一个程序的代码段来执行。

这种特殊情况,人们对fork进行了优化,重新实现了一个vfork()系统调用。主要改进有:

  • vfork()子进程不再复制父进程的地址空间内容,所以效率更高

  • vfork()保证子进程一定先运行,在它调用exec或者exit之后,父进程才能运行

进程退出

进程正常退出的话,会有return; exit(); _exit(); 线程return; pthread_exit()5 种方式。不正常退出有abort()、接受某些信号 和 线程cancellation取消。

pid_t wait(int *statloc);
pid_t waitpid( pid_t pid, int *statloc, int options );
int   waitid( idtype_t idtype, id_t id, siginfo_t *infop, int options );
pid_t wait3(int *statloc,int options,struct rusage *rusage);
pid_t wait4(pid_t pid,int *statloc,int options,struct rusage *rusage);

第 3 章 进程

PCB(Process control block)进程控制块:

  • 进程状态

  • 程序计数器:要执行的下个指令的地址

  • CPU 寄存器

  • CPU 调度信息:进程优先级、调度队列指针、调度参数

  • 内存管理信息:内存基址、界限寄存器的值、页表、段表

  • 记账信息:CPU 时间、实际使用时间、时间界限、记账数据、作业或进程数量

  • I/O 状态信息:分配给进程的 I/O 设备列表、打开的文件列表