《UNIX环境高级编程》读书笔记之进程控制

1.进程标识

每个进程都有非负整型标示的唯一进程ID。系统中有一些特殊的进程,如ID为0的进程为调度进程,常被称为交换进程(swapper)。进程ID为1的进程为init进程,此进程负责启动UNIX系统。init进程是一个普通的用户进程,但是它是以超级用户权限运行的。init进程会成为所有孤儿进程(父进程已死亡的进程)的父进程。

除了进程ID,UNIX进程还有其他一些标示符。他们可以通过下列函数得到:

#include<unistd.h>

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

get_t getegid(void)//返回进程有效组ID

2.已在运行的进程可以通过fork()创建子进程

由fork()函数创建的进程成为子进程。fork()函数被调用一次,但是返回两次。子进程的返回值为0,父进程的返回值为子进程的进程ID。

子进程和父进程继续执行fork调用后的指令。子进程取得父进程的数据空间以及栈和堆的副本(注意,子进程和父进程不共享这些存储区,它们各自保留这些数据的一份副本)。

3.文件共享

fork()的一个特性是父进程的所有打开的文件描述符都被复制到子进程中,需要注意的是,如果父进程的标准输出被重定向,则子进程的标准输出也别重定向。

4.函数wait()和waitpid()

当进程调用wait()或者waitpid()函数时,可能出现以下三种状态:

(1)如果其所有子进程都还在运行,则阻塞。

(2)如果有一个子进程已终止,正在等待父进程获取其终止状态,则取得子进程的终止状态后返回。

(3)如果它没有任何子进程。则立即出错返回。

#include <sys/wait.h>

pid_t wait(int * statloc);

pid_t waitpid(pid_t pid,int * statloc,int options);

两个函数的区别如下:

(1)在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项,可以使调用者不阻塞。

(2)waitpid可以不等待在其调用之后的第一个终止程序,它有若干选项,可以控制它所要等待的进程。

waitpid中的pid参数做如下解释:

(1)pid==-1,等待任一子进程。在此种情况下,waitpid与wait相等。

(2)pid>0,等待进程id与pid相等的进程。

(3)pid==0,等待组ID等于调用进程组ID的任一子进程。

(4)pid<-1,等待组ID等于pid绝对值的任一子进程。

options参数有三个可选的参数:

5.wait3(),wait4()

wait3()与wait4()相比于wait(),waitpid()提供多一个功能。它们允许返回进程使用资源的概况。

#include <sys/types.h>

#include <sys/wait.h>

#include <sys/time.h>

#include <sys/resource.h>

pid_t wait3(int *statloc,int options,struct rusage *rusage);

pid_t wait4(pid_t pid,int *statloc,int options,struct rusage *rusage);

资源统计信息包括用户CPU时间总量,系统CPU时间总量,缺页次数,接收到信号的次数等。

不同系统对wait系列函数的支持:

6.函数exec

用fork()函数创建新的子进程后,子进程要调用exec函数来执行另一个程序。调用exec并不创建新进程,所以前后进程的ID并没有改变。exec只是用了一个硬盘上新程序替换了当前进程的正文段、数据段、堆段、栈段。

exec系列函数:

区别:

(1)前四个取路径名做参数,后两个区文件名做参数。

(2)参数表的传递方式不同。execl,execlp,execle要求每个命令行参数在函数中单独声明为一个参数。另外的四个则先构造一个包含各参数的数组,将这个数组作为参数。

(3)以e结尾的三个函数可以传递一个指向环境字符串指针数组的指针。

7.函数system

#iclude <stdlib.h>

int system(const char * cmdstring);

如果cmdstring为一个空指针,则仅当system函数可用时返回0.这一特性可以用来判断system函数是否可用。

system在其实现中其实是调用了fork,exec,waitpid。

8.进程会计

大多数UNIX系统提供了一个选项以进行进程会计处理。启用该选项后,每当进程结束后,内核就写一个进程记录。会计记录一般包含命令名,使用的CPU时间总量,用户ID和组ID,启动时间等。

会计记录的基本样式如下:

9.进程调度

进程可以以nice值选择以更低的优先级运行。只有特权进程允许提高调度的优先级。进程可以通过nice函数得到或者提高进程的优先级。

#include <unistd.h>

int nice(int incr);

getpriority函数可以像nice函数那样获取进程的nice值,还可以获取一组相关进程的nice值。

#include <sys/resource.h>

int getpriority(int which,id_t who);

时间: 2024-10-04 00:08:23

《UNIX环境高级编程》读书笔记之进程控制的相关文章

UNIX环境高级编程第8章进程控制 8.3fork 文件共享 vfork

#include "apue.h" /* syj 20140112 */ int glob = 6; /* external variable in initialized data */ char buf[] = "a write to stdout\n"; int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(STDOUT_FI

UNIX环境高级编程学习笔记(第一章UNIX基础知识)

总所周知,UNIX环境高级编程是一本很经典的书,之前我粗略的看了一遍,感觉理解得不够深入. 听说写博客可以提高自己的水平,因此趁着这个机会我想把它重新看一遍,并把每一章的笔记写在博客里面. 我学习的时候使用的平台是Windows+VMware+debian,使用secureCRT来连接(可以实现多个终端连接). 因为第一章是本书大概的描述,所以第一章的我打算写得详细一点,而且书本的原话占的比例会比较多,重点的东西会用粗体显示出来. 1.1  引言 所有操作系统都为他们所运行的程序提供服务.典型的

Unix环境高级编程学习笔记(五):进程控制

1 getpid函数,getppid函数,得到进程id,得到父进程id #include<unistd.h> pid_t getpid(void) pid_t getppid(void) uid_t getuid(void)得到实际用户id uid_t geteuid(void)得到有效用户id gid_t getgid(void)得到实际组id gid_t getegid(void)得到有效组id 2 fork函数,当前进程创建新进程 #include<unistd.h> pid

Unix环境高级编程学习笔记(四):进程环境

1 exit函数与_Exit函数 #include<stdlib.h> void exit(int status) void _Exit(int status) 这两个函数的不同之处在于exit函数先执行清理工作后再进入内核(清理I/O缓冲),_Exit函数直接进入内核 2 atexit函数,登记函数,在exit的时候执行 int atexit(void (* func) (void)); 被登记的函数称为终止处理函数,这些函数的调用顺序与登记顺序相反,如果一个函数被登记多次,也会被调用多次

《UNIX环境高级编程》笔记——3.文件IO

一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进程共享资源(包括文件)时,会有很多额外的烦恼,需要对共享资源.原子操作等概念深入理解,需要理解涉及的内核有关数据结构,这些数据结构对理解文件.共享有重要作用: 最后介绍dup.fcntl.sync.fsync和ioctl函数. 二.文件描述符 open或creat文件时,内核--文件描述符fd-->

Unix环境高级编程学习笔记(七):线程

1 线程包含线程ID,一组寄存器的值,栈,调度优先级和策略,信号屏蔽字,errno变量,以及线程私有数据.进程的所有信息对于该进程的所有线程都是共享的,包括可执行程序文本,程序全局内存和堆内存,栈以及文件描述符. 线程可以通过pthread_self函数获得自身线程ID #include<pthread.h> pthread_t pthread_self(void) 新增进程可以通过pthread_create函数创建 #include <pthread.h> int pthrea

UNIX环境高级编程(阅读笔记)---多线程信号

多线程信号 1.默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的 2. 每个线程均有自己的信号屏蔽字,可以使用sigprocmask函数来屏蔽某个线程对该信号的响应处理,仅留下需要处理该信号的线程来处理指定的信号. 3. 对某个信号处理函数,以程序执行时最后一次注册的处理函数为准,即在所有的线程里,同一个信号在任何线程里对该信号的处理一定相同 4. 可以使用pthread_kill对指定的线程发送信号 5. 在主进程中对sigmask进行设置后,主进程创建出来的线程将继承主进

Unix环境高级编程学习笔记(三):标准I/O , 系统数据文件和信息

1 标准I/O函数不同于read,write函数,是其在流上进行操作, 当首次调用标准I/O函数时,系统会首先调用malloc,为流创造缓冲区, 2 fopen函数 #include<stdio.h> file * fopen(const char* pathname, const char * restrict name); 打开返回指针,出错返回NULL, type的取指有r(读),w(写),a(追加),r+/w+(读+写),a+(读+写+追加) int fclose(file* fp)

《Unix环境高级编程》读书笔记 第7章-进程环境

1. main函数 int main( int argc, char *argv[] ); argc是命令行参数的数目,包括程序名在内 argv是指向参数的各个指针所构成的数组,即指针数组 当内核执行C程序时(使用exec函数),在调用main前先调用一个特殊的启动例程.可执行程序文件将此启动例程指定为程序的起始地址——这是由连接器设置的,而连接器则是由C编译器调用.启动例程从内核取得命令行参数和环境变量值,然后按上述方式调用main函数做好安排. 2. 进程终止 有8种方式使进程终止,其中5种

《Unix环境高级编程》读书笔记 第3章-文件I/O

1. 引言 Unix系统的大多数文件I/O只需用到5个函数:open.read.write.lseek以及close 本章描述的函数经常被称为不带缓冲的I/O.术语不带缓冲指的是在用户的进程中对其不会自动缓冲,每个read和write都调用内核中的一个系统调用.但是,所有磁盘I/O都要经过内核的块缓存区(也称为内核的缓冲区高速缓存).唯一例外的是对原始磁盘设备的I/O. 2. 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数,其变化范围是0~OPEN_MAX