Linux--进程控制(上)


本片博客会粘贴部分代码,想要了解更多代码信息,可访问 小编的GitHub关于本篇的代码

进程创建

fork函数

#include <unistd.h>
       pid_t fork(void);

fork函数功能:在已存在的进程中创建一个新进程,新进程成为子进程,原进程称为父进程。
函数返回值:
在这里插入图片描述
根据函数返回值,我们可以

  • 对进程创建是否成功进行掌控
  • 进程创建成功后,对父子进程进行分流
    另外,子进程和父进程拥有同一块代码段,子进程和父进程的数据段采取写时拷贝的方式进行存储。
    想要让子进程去做不一样的事,这就要在分流后,仅对子进程进行操控。
    在这里插入图片描述
    虚拟地址是通过页表被映射到物理内存的,当未进行写操作,父子进程共用相同代码段和数据段,进行写操作之后,系统会给子进程新开辟一段空间,子进程会拥有自己的数据段,任然与父进程共用同一块代码段。
    vfork( )函数
#include <sys/types.h>
#include <unistd.h>
       pid_t vfork(void);

vfork函数与fork函数类似,不同点在于:

  • vfork函数的父子进程的数据段不会进行写时拷贝
  • vfork函数总是子进程运行结束之后,父进程才运行,否则可能引起混乱。

进程等待

为什么需要进程等待?

一个进程在系统中是占有系统资源的,在正常进程结束之后,系统都会对进程进行资源回收,否则会导致资源泄露,还可能影响其他进程,比如僵尸进程的形成,就是因为父进程没有回收子进程所占有的的系统资源导致的。

因此创建了子进程之后,在进程结束前,父进程要进程等待子进程,并回收子进程的系统资源。

怎么进程等待?

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

这两个函数的特点:

  • wait和waitpid函数都是用等待子进程的函数,默认情况下,这两个函数都会阻塞(等不到就一直等)等待子进程。如果成功返回子进程ID,如果失败返回-1.

进程等待结果

  • wait和waitpid函数都有一个status参数,该参数是一个输出型参数,由操作系统填充,用来获取进程的退出码,退出码中有进程退出的原因,在调用函数时候,如果不关心子进程的退出原因可以置空。这个退出码是一个四字节的整型变量,实际上操作系统只需要用两个字节(用了低16位的两个字节):
    在这里插入图片描述
    如上图|所示
  • waitpid函数独有的两个参数
    pid 常用的参数值:
取值含义
0等待进程ID与目前进程相同的任何子进程
-1等待任意子进程
其他等待进程ID等于|pid|的进程

可见wait函数等待任意子进程,waitpid既可以等待任意子进程,也可以等待指定子进程

options:选项常用参数

取值含义
WNOHANG非阻塞等待(如果没有子进程退出,则立即返回)
0阻塞等待(如果没有等到子进程退出就一直等待)

可见wait函数只能是阻塞等待,waitpid函数既可以阻塞等待,也可以非阻塞等待
waitpid函数的百科解释

进程终止

进程退出的状况:
1、代码运行完毕,结果正确退出
2、运行完毕,结果错误退出
3、异常退出
退出方式:
1、main函数返回值退出 (return只有在main函数中才能退出进程)
2、exit()在程序任意位置调用都会逐步退出进程,执行用户定义的清理函数、冲刷缓冲区、关闭文件,退出时候会释放所有资源(操作+调用_exit)
3、_exit粗暴的直接退出进程,资源直接释放掉
进程退出码:perror、strerror
\n换行刷新缓冲区

程序替换

替换方法:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

l参数列表形式
v数组形式
p自动搜索环境变量PATH
e由用户自己组织环境变量

代码练习

#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>

int main(){
    int pid=-1;
    //进程创建
    pid=fork();
    if(pid<0){
        perror("fork error");
        return -1;
    }else if(pid==0){
        //子进程进程替换
        //int execl(const char *path, const char *arg, ...);
        //这个函数参数由两部分组成,const char *path是需要给出替换的程序源路径,后一部分以可变参数列表形式给出,替换内容,以NULL标志结尾
        execl("/usr/bin/ls","ls","-al",NULL);
        exit(0);//子进程终止,返回退出码0
    }
    //进程等待
    int status;
    waitpid(-1,&status,0);
    if((status&0x7f)==0)//0x7f是16进制数,换算成二进制是0111 1111,也就是取出status的低7位
    {
        printf("child exit num is %d",status>>8);//取出退出码
    }else{
        printf("cause child procee exit signal %d",status&0x7f);//异常退出码
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值