Linux----进程控制(下)

news/2024/7/7 16:24:29

Linux----进程控制(下)

  • 3)进程等待
    • wait()
    • waitpid()
      • ①status
      • ②option(阻塞与非阻塞)
  • 4)进程程序替换
    • 替换函数
      • ①execl系列(l:list)
      • ②execv系列(v:vector)
    • 场景

3)进程等待

进程等待的意义:

  1. 回收僵尸进程(解决内存泄漏)
  2. 需要获取子进程的运行结束状态(不是必要)
  3. 父进程晚于子进程退出,可以规范化进行资源回收(编码)

wait()

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);


返回:等待任意一个子进程,当子进程退出,wait就可以返回,成功返回被等待进程pid,失败返回-1
int*status:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL


例:

int main()
{
	pid_t id=fork();
	if(id<0){
	    perror("fork");
	    return 1;
	}
	else if(id==0){
	    int count=5;
	    while(count--){
	        printf("child running: %d,pid:%d,ppid:%d\n",count,getpid(),getppid());
	        sleep(1);
	    }
	    printf("child quit...\n");
	    exit(0);
	}
	else{
	    printf("father is waiting...\n");
	    sleep(10);//让子进程维持5s的z状态
	    pid_t ret=wait(NULL);
	    printf("father wait done,ret is: %d\n",ret);
	}
	return 0;
}

shell监测脚本:

while :; 
do 
echo "===================================";
ps ajx | grep test1 | grep -v grep;
echo "===================================";
sleep 1;
done

在这里插入图片描述

waitpid()

#include <sys/wait.h>
pid_ t waitpid(pid_t pid, int *status, int options);


返回:

  1. 当正常返回的时候waitpid返回收集到的子进程的进程ID
  2. 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0
  3. 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在

pid:

  1. pid=(pid_t)-1,等待任一个子进程,与wait()等效
  2. pid>0,等待其进程ID与pid相等的子进程(等待指定的子进程:fork返回给父进程)
  3. pid=0,则请求其进程 组 ID 等于调用进程的任何子进程的状态(略)
  4. pid<(pid_t)-1,则为进程 组 ID 等于 pid 绝对值的任何子进程请求状态(略)

status:

  1. WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
  2. WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

options:

  1. WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID

例:

int main()
{
	pid_t id=fork();
	if(id<0){
	    perror("fork");
	    return 1;
	}
	else if(id==0){
	    int count=5;
	    while(count--){
	        printf("child running: %d,pid:%d,ppid:%d\n",count,getpid(),getppid());
	        sleep(1);
	    }
	    printf("child quit...\n");
	    exit(121);
	}
	else{
	    printf("father is waiting...\n");
	    sleep(10);//让子进程维持5s的z状态
	    int status=0;
	    pid_t ret=waitpid(-1,&status,0);
	    int code = (status>>8)& 0xFF;
	    printf("father wait done,ret is the pid of child process: %d\n",ret);
	    printf("The code is: %d\n",code);
	    if(code==0)
	    {
	        printf("success\n");
	    }
	    else
	        printf("wrong\n");
	}
	return 0;
}

在这里插入图片描述

①status

wait和waitpid都有一个status参数
int status共32位,下图是低16位在这里插入图片描述
当子进程正常终止时用(status>>8)& 0xFF可以得到退出状态(不会收到任何信号)
当子进程异常终止(收到OS发送的信号),同时带有一位的core dump标志位,用status & 0x7F可以获得


例如下面由于段错误子进程终止:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


两个宏函数WIFEXITED和WEXITSTATUS可以用来判断子进程退出状态(正常/异常终止)

if(WIFEXITED(status)){
	printf("quit normal\n");
	printf("quit code is: %d\n",WEXITSTATUS(status));
}
else
	printf("process quit error\n");

在这里插入图片描述


问1:为什么不设置一个全局变量code,而要返回退出码?
:写时拷贝,子进程不能更改code
问2:waitpid从哪里拿到的status值的?子进程已经退出了
:子进程处于Z(僵尸状态),有内存泄漏(还有数据),waitpid从task_struct中获得的
下面是linux-2.6.39的源码 (进程退出码最终会被写入到exit_code里)
在这里插入图片描述

②option(阻塞与非阻塞)

如果option选项传入的是WNOHANG就是非阻塞等待方式,如果option传的是0默认是阻塞


非阻塞:
在这里插入图片描述
这里一共有三种返回状态:

  1. 失败返回(下一次再检测)
  2. 失败返回(真正的失败)
  3. 成功返回

阻塞等待理解:
在这里插入图片描述
阻塞等待:父进程等待,子进程运行

  1. 这里的“等待”:指OS把父进程放入等待队列,并将进程状态设置为非R状态
  2. 子进程运行完了再唤醒父进程,将父进程从等待队列中取出,放入运行队列,同时将其设为R状态

4)进程程序替换

进程程序替换

  1. 通过exec系列函数,让特定进程去加载磁盘中的其他程序,已达到运行的目的,期间不创建新的进程

为什么要进程程序替换:

  1. 子进程执行父进程的一部分代码
  2. 子进程自身新的程序需求

替换函数

头文件:#include <unistd.h>
返回:

  1. 如果调用成功则加载新的程序从启动代码开始执行,不再返回
  2. 如果调用出错则返回-1

只有execve是真正的系统调用,其它五个函数最终都调用 execve,这些函数之间的关系如下图:
在这里插入图片描述

①execl系列(l:list)

int execl(const char *path, const char *arg, ...);


path:执行的程序(带路径)
arg...:给执行程序传递的参数(…是可变参数)必须以NULL结尾


int execlp(const char *file, const char *arg, ...);


file:执行的程序(不带路径,会自动到环境变量找)
arg...:给执行程序传递的参数(…是可变参数)必须以NULL结尾


int execle(const char *path, const char *arg, ...,char *const envp[]);


path:执行的程序(带路径)
arg...:给执行程序传递的参数(…是可变参数)必须以NULL结尾
envp:传入默认的或者自定义的环境变量给目标可执行程序

②execv系列(v:vector)

int execv(const char *path, char *const argv[]);


path:执行的程序(带路径)
arg[]:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾


int execvp(const char *file, char *const argv[]);


file:执行的程序(不带路径,会自动到环境变量找)
arg[]:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾


int execve(const char *path, char *const argv[], char *const envp[]);


path:执行的程序(带路径)
arg[]:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
envp[]:传入默认的或者自定义的环境变量给目标可执行程序


int execvpe(const char *file, char *const argv[], char *const envp[]);


file:执行的程序(不带路径,会自动到环境变量找)
arg[]:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
envp[]:传入默认的或者自定义的环境变量给目标可执行程序


场景

shell解释器fork()创建子进程执行命令
Linux----50行简易shell


http://www.niftyadmin.cn/n/4608922.html

相关文章

安卓应用安全指南 4.2.2 创建/使用广播接收器 规则书

4.2.2 创建/使用广播接收器 规则书 原书&#xff1a;Android Application Secure Design/Secure Coding Guidebook 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 遵循下列规则来发送或接受广播。 4.2.2.1 仅在应用中使用的广播接收器必须设置为私有&#xff08;必需…

Linux----IO(初级)

Linux----IO&#xff08;初级&#xff09;1&#xff09;C文件I/O2&#xff09;系统文件I/O①Linux一切皆文件&#xff08;补缓冲区&#xff09;②IO系统接口③站在系统角度理解④file descriptor&#xff08;文件与进程&#xff09;⑤分配文件描述符的规则⑥C中的FILE⑦重定向3…

Web API(二):Web API概述

一、什么是API API&#xff08;Application Programming Interface&#xff09;即应用程序编程接口&#xff0c;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而无需访问源代码&#xff0c;或者理解内部的…

C++进阶----继承

C进阶----继承1)继承①继承父类成员访问方式的变化②父子类赋值转换③隐藏(重定义)④子类的4个默认成员函数(const取地址略)子类构造函数子类拷贝构造子类赋值重载子类析构函数⑤友元⑥静态成员⑦菱形继承⑧虚继承(virtual)⑨组合1)继承 概念&#xff1a; 继承机制是面向对象程…

C++进阶----多态

C进阶----多态2&#xff09;多态①多态实现虚函数重写Ⅰ.特例1--协变Ⅱ.特例2--析构函数重写override final重载 / 重写 / 隐藏②抽象类&#xff08;纯虚函数&#xff09;③虚函数表④其他虚函数表单继承虚函数表&#xff08;vs省略的派生类虚函数表内容&#xff09;多继承虚函…

TCP/IP 中的OSI分层模型详解

一 连接人与人的计算机网络 计算机网络最初的目的是连续一个个独立的计算机&#xff0c; 使他们组成一个个更强有力的计算环境。简而言之&#xff0c;就是为了提高生产力。从批处理时代到计算机网络时代&#xff0c; 毋庸置疑&#xff0c;都体现了这一目的。然而&#xff0c;现…

iscroll在谷歌浏览器中bug

https://segmentfault.com/q/1010000008489619 iscroll 在安卓app嵌套html页面时&#xff0c;导致列表页滑动不起来&#xff0c;并且在chorme浏览器中使用手机模式&#xff0c;也滑动不起来&#xff0c; 在scroll插件的IScroll函数最后增加 document.addEventListener(touchmov…

unity3d入门之添加背景音乐

我使用的是unity3d 4.6 在添加音频之前&#xff0c;你的电脑里要有音频&#xff0c;可以随便下载一首&#xff0c;这里我只讲怎么实现功能&#xff0c; 下载的音频最好放在英文目录下&#xff0c;并且你要记得路径&#xff0c;这样才可以右击asset然后import你想要的音频。 1、…