Linux系统编程(二)

复习文件描述符(指向结构体的指针)
这里写图片描述
exec函数族
fork创建子进程后执行的是和父进程相同的程序(但是有可能执行不同的代码分支)子进程往往要调用一种exec函数以执行另外一个程序,当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替代,从新程序的启动例程开始执行,调用exec并不创建新的进程,所以调用exec前后进程的ID并未改变。
重点掌握
execlp函数
加载一个进程,借助PATH环境变量
int execlp(const char *file, const char *arg, …);
参数1 要加载的程序的名称该函数要配合PATH环境变量来使用,当PATH中所以目录搜索后没有参数1时则出错返回
该函数通常用来调用系统程序如:ls date cp cat 等命令

    #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 int main(void)
  5 {
  6     pid_t pid;
  7     pid = fork();
  8     if(pid == -1){
  9         perror("fork error");
 10         exit(1);
 11         }else if(pid > 0)
 12         {
 13             sleep(1);
 14             printf("parent\n");
 15             }else{
 16                 execlp("ls","ls","-l",NULL);
 17        /*函数使用的参数几点注意①第一个参数是可执行程序名 ②必须以NULL结尾③对第二个参数没有要求*/                      
 18                 }
 19     return 0;
 20     }

补充 命令行参数
描述命令行参数的个数 argc
命令行参数的数组 argv
execl 函数
加载一个进程 通过路径+程序名

execl("/bin/ls","ls","-l",NULL);

execv函数

/*其它部分相同*/
char *argv[] = {"ls","ls","-l",NULL};
execv("/bin/ls",argv);

练习:将当前系统中的信息打印到文件中 主要open dup2 execlp 函数
dup2函数:完成文件描述符的拷贝
这里写图片描述

#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int fd;
fd = open("ps.out",O_WRONLY|O_CREAT|O_TRUNL,0644);
if(fd < 0){
perror("open ps.out error");
exit(1);
}
    dup2(fd, STDOUT_FILENO);    //dup2(3,1)   fd   stdout
    execlp("ps","ps","ax",NULL);
    perror("exec error");
    exit(1); //出错处理
    return 0;

}

总结 exec函数一旦调用成功即执行新的程序不返回,只有失败才返回-1所以通常我们直接在exec函数调用后直接调用perror()和exit()无需if判断
回收子进程
孤儿进程
父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程 称为init进程领养孤儿进程
僵尸进程
进程终止,父进程尚未回收,子进程残留资源(PCB)存放在内核中,变成僵尸进程。
Wait函数
三个功能:
①阻塞等待子进程退出
②回收子进程残留资源
③获取子进程结束状态
pid_t wait(int *status);注意是传出参数,需要定义一个变量接受它。成功:清理掉子进程的ID,失败:-1
可借助wait函数传出参数status来保存进程的退出状态。借助宏函数来进一步来判断进程终止的具体原因
1 WIFEXITED( status) 为非0 进程正常结束
WEXITSTATUS(status) 如果上宏为真,实用此宏可以获取进程退出状态(exit的值)
2 WIFSIGMALED(status) 非0 进程异常终止
WTERMSIG(status) 如果上宏为真,实用宏取得使进程终止的那个信号的编码

//主要部分
if( WIFEXITED( status)){
printf("child exit with %d\n",WEXITSTATUS(status); 
}if(WIFSIGMALED(status)){
printf("child killed by %d\n",WTERMSIG(status));
}

回收多个子进程用循环
一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环

while(wait(NULL))
      ;
      //或者
      while(waitpid(-1,NULL,0));  //   参3 为0时阻塞状态

这里写图片描述
不同点 第三个参数 WNOHANG 会探测子进程是否结束,为非阻塞状态,轮循结构使用do while

int n = 5    //子进程个数
pid_t wpid;
 do{
    wpid = waitpid(-1,NULL,0);
    if(wpid > 0){
    n--;
    }
    sleep(1);
}while(n > 0);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值