Linux进程fork()、exit()、wait()、exec族、system函数、popen函数

本文详细介绍了Linux进程管理的相关概念,包括进程的创建(fork)、退出(exit)、等待(wait)、exec族函数以及system和popen函数的使用。通过多个实战例子展示了如何在C语言中运用这些函数,帮助读者深入理解Linux进程操作。
摘要由CSDN通过智能技术生成

进程相关概念、创建进程fork()、进程退出exit()、等待函数wait()、exec族、system函数、popen函数

一、进程相关概念

问1. 什么是程序,什么是进程,有什么区别?
程序是静态的概念,gcc xxx.c –o pro,磁盘中生成pro文件。
进程是程序的一次运行活动,通俗点意思是程序跑起来了,系统中就多了一个进程。
问2. 如何查看系统中有哪些进程?
a. ps -aux|grep +(程序名)
b. top指令查看,类似于任务管理器。
问3. 什么是进程标识符?
每个进程都有一个非负整数表示的唯一ID,叫做pid,类似身份证。
特别地:
Pid=0: 称为交换进程(swapper)作用—进程调度
Pid=1:init进程作用—系统初始化。
获取pid值:
调用getpid函数获取自身的进程标识符。
getppid获取父进程的进程标识符。
问4. 什么叫父进程,什么叫子进程?
进程A创建了进程B。那么A叫做父进程,B叫做子进程,
问5. C程序的存储空间是如何分配?
在这里插入图片描述
正文段:代码段
初始化的数据:数据段
未初始化的数据:bss段通常是用来存放程序中未初始化的全局变量和静态变量
堆:malloc等函数申请临时空间
栈:函数调用、局部变量

二、创建进程

fork头文件和函数

// 头文件
#include <unistd.h>
#include <sys/types.h>
//函数
pid_t fork(void);
//返回:success 返回两次 返回值为0 代表当前进程是子进程
//					   返回值为非负数 代表当前进程是父进程,返回值为子进程ID

pid_t 实质是 int 被定义在 #include<sys/types.h>

fork创建子进程的目的

  • 一个父进程复制自己,父、子进程同时执行不同代码段。父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork。使得子进程处理这种请求,父进程继续下一请求。

  • 一个进程执行不同的程序,这是shell常见的情况,这种情况下fork返回立即调用exec。

fork写时拷贝
Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至避免拷贝数据的技术。内核此时并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间。只用在需要写入的时候才会复制地址空间,从而使各个进行拥有各自的地址空间。
也就是说,资源的复制是在需要写入的时候才会进行,在此之前,只有以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。
vfork与fork的区别
区别一:vfork直接使用父进程储存空间,不拷贝。
区别二:vfork保证子进程先运行,当子进程exit后,父进程运行。
区别一举例说明:当子进程修改变量a=10时,那么父进程中的a也改成了10。

三、进程退出

正常退出

  1. Main函数调用return
  2. 进程调用exit(),标准C语言库
  3. 进程调用_exit()或者_Exit(),属于系统调用
  4. 进程最后一个线程返回
  5. 最后一个线程调用pthread_exit

异常退出

  1. 调用abort函数
  2. 当进程收到某些信号时,如ctrl+C
  3. 最后一个线程对取消(cancellation)请求做出响应

正常线程退出使用pthread_exit(),进程退出调用exit()。不论时正常还是异常退出状态下,子进程需要传参父进程,使得父进程知道子进程运行状态,将运行状态status传递给wait或者waitpid参数。
下面展示一些 exit代码片

// exit头文件
#include <stdlib.h>
//exit主函数
void exit(int status);
//_exit头文件
#include <unistd.h>
//_exit主函数
void _exit(int status);
//_Exit头文件
#include <stdlib.h>
//Exit主函数
void Exit(int status);

四、进程等待

进程等待函数的意义:父进程等待子进程退出,并收集子进程的退出状态。如果子进程的退出状态不被收集,变成僵尸进程(zombie)。

下面展示一些 wait()、waitpid()头文件和主函数

// 头文件
#include <sys/types.h>
#include <sys/wait.h>
//主函数
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
//返回
// success 返回  子进程ID ;  error 返回  -1

下面展示一些 参数解释

status:是一个整型数指针
非空:子进程退出状态放在它所指向的地址中。
空:不关心退出状态。
一般想要获取status的返回值,所用函数为WEXITSTATUS(status)。举例说明,如果检测子进程exit(3),可以得到WEXITSTATUS(status)=3,用法如下:
wait(status);
printf(“father process, status = %d\n”,WEXITSTATUS(status));

pid_t pid的取值
pid==-1,等待任一子进程,此时和wait()等效。
pid>0,等待与pid值一致的子进程。
pid==0,等到其组ID和调用进程的组ID相等的任一子进程。
pid<-1,等到其组ID和pid绝对值相等的任一子进程。

options的取值可以取0,或者取下列组合:
WCONTINUED:pid指定的任一子进程在暂停后已经继续,但其状态尚未报告,则返回其状态。
WNOHANG:常用,waitpid将不阻塞如果指定的pid并未结束。
WUNTRACED:如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。

孤儿进程
含义:父进程先结束,子进程后结束。子进程就变成了孤儿进程。
Linux处理方法:Linux避免存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。

**pr_exit(status)**打印status的数值
下面展示一些 pr_exit()代码段

// pr_exit()函数
void pr_exit(int status)
{
	if(WIFEXITED(status)){
		printf("normal termination, exit status =  %d\n",WEXITSTATUS(status));
	}elseif (WIFESIGNALED(status)){
		printf("abnormal termination, exit status =  %d\n",WTERMSIG(status));
	}
}

五、exec族

功能:
  在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
  当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
函数族:
  exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe

// 头文件
#include <unistd.h>
//主函数
extern char **environ;

 int execl<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值