⭐❤️进程的进阶讲解❤️⭐

1.进程的挂起

进程在一定的时间内没有任何动作,称为进程的挂起 #include <unistd.h> unsigned int sleep(unsigned int sec);
功能:进程挂起指定的秒数,直到指定的时间用完或收到信号才解除挂起。
返回值:若进程挂起到 sec 指定的时间则返回 0,若有信号中断则返回剩余秒数。 注意:进程挂起指定的秒数后程序并不会立即执行,系统只是将此进程切换到就绪态。

2.进程的等待

父子进程有时需要简单的进程间同步,如父进程等待子进程的结束。
linux 下提供了以下两个等待函数 wait()、waitpid()。
需要包含头文件:
#include <sys/types.h>
#include <sys/wait.h>

wait 函数

pid_t wait(int *status)
功能:等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。
 调用 wait 函数的进程会挂起,直到它的一个子进程退出或收到一个不能被忽视的信号时才被唤醒。
 若调用进程没有子进程或它的子进程已经结束,该函数立即返回。 
 参数:函数返回时,参数 status 中包含子进程退出时的状态信息。
 子进程的退出信息在一个 int 中包含了多个字段, 用宏定义可以取出其中的每个字段。
  返回值:如果执行成功则返回子进程的进程号。 
  出错返回-1,失败原因存于 errno 中

waitpid 函数

pid_t waitpid(pid_t pid, int *status,int options)
 功能: 等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。
 返回值: 
	 如果执行成功则返回子进程 ID。
	 出错返回-1,失败原因存于 errno 中。
 参数 pid 的值有以下几种类型:
  pid>0:等待进程 ID 等于 pid 的子进程。
  pid=0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid 不会等待它。
  pid=-1:等待任一子进程,此时 waitpid 和 wait 作用一样。 pid<-1:等待指定进程组中的任何子进程,这个进程组的 ID 等于 pid 的绝对值。
  status
   参数中包含子进程退出时的状态信息。
  options
    参数能进一步控制 waitpid 的操作:
     0: 同 wait,阻塞父进程,等待子进程退出。
     WNOHANG: 没有任何已经结束的子进程,则立即返回。 WUNTRACED 如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结束状态。(跟踪调试,很少用到)
     返回值: 
     成功:返回状态改变了的子进程的进程号;如果设置了选项 WNOHANG 并且 pid 指定的进程存在则返回 0。 
     出错:返回-1。当 pid 所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid 就会出错返回,这 时 errno 被设置为 ECHILD。

特殊进程

  • 僵尸进程
    结束后没有回收资源,一直占用着系统资源,但其实没有任何的用处,属于一种BUG。
  • 守护进程
    属于孤儿进程的一种,这种进程脱离终端,在后台进行
  • 孤儿进程
    子进程还没有结束,父进程就已经结束了,孤儿进程统一归属某个专门的进程管理

结束进程

  • void exit(int value)

  • _exit (int value)

  • exit 为库函数,而_exit 为系统调用-,两者的参数一般给NULL

进程的创建 vfork 函数

pid_t vfork(void)
 功能:vfork 函数和 fork 函数一样都是在已有的进程中创建一个新的进程,但它们创建的子进程是有区别的。 
 返回值: 创建子进程成功,则在子进程中返回 0,父进程中返回子进程 ID。出错则返回-1。
  fork 和 vfork 函数的区别: vfork 保证子进程先运行,在它调用 exec 或 exit 之后,父进程才可能被调度运行。 vfork 和 fork 一样都创建一个子进程,但它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即 调用 exec(或 exit),于是也就不访问该地址空间。 相反,在子进程中调用 exec 或 exit 之前,它在父进程的地址空间中运行,在 exec 之后子进程会有自己的进程 空间

在这里插入图片描述

exec 函数族

exec 函数族,由六个exec函数组成
1、exec 函数族提供了六种在进程中启动另一个程序的方法。
2、exec 函数族可以根据指定的文件名或目录名找到可执行文件。
3、调用 exec 函数的进程并不创建新的进程,故调用 exec 前后,进程的进程号并不会改变,其执行的程序完 全由新的程序替换,而新程序则从其 main 函数开始执行。

 #include <unistd.h>
 #include <unistd.h> 
 int execl(const char *pathname, const char *arg0,, NULL);
 int execlp(const char *filename, const char *arg0,, NULL); 
 int execle(const char *pathname, const char *arg0,,NULL, char *const envp[]); 
 int execv(const char *pathname, char *const argv[]);
 int execvp(const char *filename, char *const argv[]);
 int execve(const char *pathname, char *const argv[], char *const envp[]);
 l(list):参数地址列表,以空指针结尾。 参数地址列表 char *arg0, char *arg1, ..., char *argn, NULL 
 v(vector): 存有各参数地址的指针数组的地址。 使用时先构造一个指针数组,指针数组存各参数的地址,然后将该指针数组地址作为函数的参数。
 p(path) 按 PATH 环境变量指定的目录搜索可执行文件。 以 p 结尾的 exec 函数取文件名做为参数。当指定 filename 作为参数时,若 filename 中包含/,则将其视为 路径名,并直接到指定的路径中执行程序。 
 e(environment): 存有环境变量字符串地址的指针数组的地址。execle 和 execve 改变的是 exec 启动的程序的环境变量(新的 环境变量完全由 environment 指定),其他四个函数启动的程序则使用默认系统环境变量。

六个 exec 函数中只有 execve 是真正意义的系统调用(内核提供的接口),其它函数都是在此基础上经过封装 的库函数。

system 函数

#include <stdlib.h>
int system(const char *command);
功能:system 会调用 fork 函数产生子进程,子进程调用 exec 启动/bin/sh -c string 来执行参数 string 字符串所 代表的命令,此命令执行完后返回原调用进程。
 参数:要执行的命令的字符串。 
 返回值:如果 command 为 NULL,则 system()函数返回非 0,一般为 1。 如果 system()在调用/bin/sh 时失败则返回 127,其它失败原因返回-1。
  注意: system 调用成功后会返回执行 shell 命令后的返回值。其返回值可能为 1127 也可能为-1,故最好应再 检查 errno 来确认执行成功
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔动山霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值