Linux进程及常用函数介绍

其余相关内容可参考个人博客

概念介绍

进程-资源分配的基本单位

进程:通俗的讲就是一个程序运行的实例,是具有一定独立功能的程序在一个数据集合上的一次动态执行过程,它是动态的,包括创建,调度,执行和消亡。

特殊进程含义

名称含义
僵尸进程子进程结束,父进程没有调用wait来回收资源
孤儿进程父进程结束,子进程还在运行
守护进程(精灵进程)后台运行的孤儿进程

孤儿进程的取消方法:因为父进程已经结束了,所在的进程组就没有了,接收不到终端发过来的结束信号,所以要用ps,然后用kill杀掉

ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'这条命令可以查看僵尸进程

进程组的概念

一个进程会有如下 ID:

  1. PID:进程的唯一标识。如果一个进程含有多个线程,所有线程调用 getpid 函数会返回相同的值。
  2. PGID:进程组 ID。每个进程都会有进程组 ID,表示该进程所属的进程组。默认情况下新创建的进程会继承父进程的进程组 ID。
  3. SID:会话 ID。每个进程也都有会话 ID。默认情况下,新创建的进程会继承父进程的会话 ID。
  4. PPID:是程序的父进程号

进程组和会话在进程之间形成了两级的层次关系,ps axjf可查看.

《Linux环境编程:从应用到内核》这本书里,有一个解释,说的比较生动形象

  1. 可以打个比方,以家族企业的创业为例,每个进程可以比喻成家族企业的每个成员。
  2. 如果从创业之初,所有家族成员都安分守己,循规蹈矩,默认情况下,就只会有一个公司、一个部门。但是也有些“叛逆”的子弟,愿意为家族公司开疆拓土,愿意成立新的部门。
  3. 这些新的部门就是新创建的进程组。如果有子弟“离经叛道”,甚至不愿意呆在家族公司里,他别开天地,另创了一个公司,那这个新公司就是新创建的会话组。由此可见,系统必须要有改变和设置进程组 ID 和会话 ID 的函数接口,否则,系统中只会存在一个会话、一个进程组

知识点总结

  1. 子进程正常退出后,会变成僵尸进程,剩余一些信息以供父进程获取,父进程必须使用wait或者waitpid来清理子进程

  2. 子进程结束时,会向父进程发送SIGCHLD信号,以便父进程回收资源

  3. 父进程退出时,若有未回收的资源,那么init进程会代为回收

  4. 父进程退出时,若有运行中的子进程,它们会被init进程领养(即父进程改为1)

  5. 父进程退出时,可使用prctl来通知子进程退出,即向子进程发送信号,例如prctl(PR_SET_PDEATHSIG,SIGKILL)

  6. fork之后父子进程的执行顺序是不确定的,这取决于内核的调度算法

  7. fork之后父子进程的缓冲区和文件位移量也会被复制

进程相关函数

函数汇总:

函数功能
创建进程
fork创建子进程,父子进程同时运行
vfork创建子进程,子进程先运行
获取进程ID
getpid获取本进程ID
getppid获取父进程ID
等待子进程
wait等待任意子进程
waitpid等待指定pid的子进程
注册终止函数
atexit注册终止函数
system函数
system注执行command命令册终止函数

函数详细介绍请见下文:

创建进程

  1. pid_t fork(void);
    功能:创建子进程
名称说明备注
参数void1.fork复制父进程的各种信息,包括缓冲区和文件偏移量等
2.父子进程同时运行
返回值pid_t对于父进程返回子进程ID,对于子进程返回0
  1. pid_t vfork(void);
    功能:创建子进程
名称说明备注
参数void1.与父进程共用堆栈,用vfork一般都会调用exec来重新加载代码段和数据段
2.保证子进程先运行等待子进程调用exit或者exec之后父进程才可能被调度运行(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁)
3.注意用vfork创建子进程中,不能用return结束子进程,因为父子进程公用堆栈,return会弹栈,让程序认为父进程已经结束,会有出乎意料的后果,所以要用exit来结束
返回值pid_t对于父进程返回子进程ID,对于子进程返回0

获取进程ID

  1. pid_t getpid(void);

获取本进程ID,返回值即为结果。
2. pid_t getppid(void);

获取父进程ID,返回值即为结果。

等待子进程

  1. pid_t wait(int *wstatus);
    功能:等待任意子进程
名称说明备注
参数wstatus该参数返回子进程的终止状态,可用宏查看1.只要有一个子进程结束了,就会立刻返回,继续运行程序了,如果一个子进程已经终止了,是僵尸进程,那么wait立即返回
2.使用宏查看子进程返回状态
(1)WIFEXITED(status)为真表示子进程正常返回
(2)WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,例如子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5

(3)WIFSIGNALED(status) 为真表示子进程异常返回
(4)WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏

(5)WIFSTOPPED(status) 为真表示当前子进程被在暂停
(6)WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏
返回值pid_t已终止的子进程PID
  1. pid_t waitpid(pid_t pid, int *wstatus, int options);
    功能:等待指定pid的子进程
名称说明备注
参数pidpid参数<-1,等待进程组ID和pid绝对值相同的任意子进程
pid参数=-1,等待任意子进程
pid参数=0,等待本进程组内的任意子进程
pid>0,等待指定pid的子进程
1.waitpid(-1, &status, 0)和wait功能一样
2.status部分和wait函数相同
wstatus该参数返回子进程的终止状态,可用宏查看
optionsoption参数为WNOHANG,若等待的子进程未结束则立刻返回,无阻塞
option参数为WUNTRACED,若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会
返回值pid_t已终止的子进程PID

注册进程终止函数

int atexit(void (*function)(void));

功能:注册进程终止函数

名称说明备注
参数function注册的函数1.在进程正常退出时,所有注册的终止函数将被执行,注意:调用_exit和_Exit函数退出的不执行清理动作,也就不会执行终止函数
2.可注册最多32个终止函数,后注册的先执行
返回值int成功返回0,失败返回非0

system函数

int system(const char *command);

功能:该函数使用fork创建一个子进程,该子进程使用execl执行指定的shell命令

名称说明备注
参数command被执行的命令执行期间,阻止SIGCHLD信号,并且忽略SIGINT和SIGQUIT信号
返回值int1.若command为NULL,返回非0值
2.若创建子进程失败返回-1
3.创建的子进程的状态通过返回值返回,可参考wait函数对子进程返回状态的处理来判断是否成功

exec函数族介绍

  1. 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替
  2. exec中的函数执行成功后不会返回,只有失败了才会返回-1,失败后接着从源程序的地方往下执行
  3. 常与vfork一起使用

函数原型如下:

int execl(const char *pathname, const char *arg, ... /* (char  *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char  *) NULL */);
int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char *const envp[] */);

int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
int execve(const char *pathname, char *const argv[], char *const envp[]);
函数特点
execl基础函数,提供程序路径和参数,参数通过arg分别传入,以NULL结尾
execlp较execl相比,提供的程序可不带路径,而自动到PATH环境变量下查询
execle较execl相比,提供的程序可不带路径,而自动到PATH环境变量下查询,调用本函数时,可使用envp参数设置环境变量,若不填写envp参数,则继承父进程的环境变量,envp也以NULL结尾
execv较execl相比,参数通过argv[]数组参入,数组中的参数还是以NULL结尾
execvp较execlp相比,参数通过argv[]数组参入,数组中的参数还是以NULL结尾
execvpe较execle相比,参数通过argv[]数组参入,数组中的参数还是以NULL结尾
execve较execv相比,可提供环境变量(该函数需要提供可执行文件全路径)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值