操作系统--进程:从函数退出到程序替换与进程等待

我们的shell其实就相当于进程替换,学了进程替换就可以手搓命令行了

目录

一、函数退出与进程结束

二、进程等待

三、程序替换


一、函数退出与进程结束

  1. main 函数退出
    • 在 C/C++ 程序中,当main函数执行完毕时,进程通常会结束。这是最常见的进程结束方式之一。例如:
int main() {
    // 一些代码
    return 0;
}
  • main函数中的代码执行完成,并且没有其他后台进程在运行时,整个程序的执行就会终止。
  1. exit 函数表示进程结束
    • exit函数可以在代码的任何地方被调用,以立即终止进程的执行。它会进行一些清理工作,如关闭文件描述符、刷新缓冲区等。例如:
void someFunction() {
    // 在某个函数中调用 exit
    exit(0);
}
  1. _exit 与 exit 的区别及缓冲区问题
    • _exitexit都用于终止进程,但它们在处理缓冲区方面有所不同。
    • _exit会直接丢弃缓冲区内容,而exit会先打印缓冲区内容。这是因为exit在终止进程之前会进行一些清理工作,包括刷新缓冲区。
    • 在 C/C++ 中,语言级缓冲区不在操作系统内部。例如,当使用printf输出内容时,数据可能会先被存储在缓冲区中,直到缓冲区满或者遇到换行符等情况才会被输出到屏幕上。如果使用_exit,这些未输出的内容可能会被丢弃。而使用exit,则会确保缓冲区中的内容被输出。

二、进程等待

  1. 一般情况

    • 父进程创建子进程后,通常需要等待子进程结束,以便回收子进程的资源和获取子进程的退出状态。
    • 等待的时候,子进程不退,父进程就要阻塞在wait内部。
  2. wait 函数

    • wait函数用于等待子进程结束,并返回子进程的 PID。它会阻塞父进程,直到有一个子进程结束。
    • 例如:
pid_t pid = fork();
if (pid == 0) {
    // 子进程代码
    exit(0);
} else {
    int status;
    pid_t child_pid = wait(&status);
    // 处理子进程的退出状态
}
  1. waitpid 函数
    • waitpid函数提供了更多的控制选项。它可以指定要等待的子进程的 PID,以及设置等待的方式(阻塞或非阻塞)。
    • 参数说明:
      • pid:大于 0 时指定要等待的子进程的 PID;等于 -1 时表示等待任意子进程。
      • status:用于获取子进程的退出信息,不仅仅包含进程退出码。第八位到 16 位是退出码,可以通过(status>>8)&0xFF获取退出码;通过status&0x7F获取退出信号。
      • options:默认是 0,表示阻塞等待;可以设置为WNOHANG表示非阻塞等待,进行轮询检测。
    • 返回值:pid_t > 0表示等待成功,返回目标子进程的 PID;==0表示等待成功,但子进程没有退出;<0表示等待失败。

三、程序替换

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3  #include<sys/wait.h>
  4 #include<unistd.h>
  5 #include<stdlib.h>
  6 int main(){
  7      pid_t id = fork();
  8      if(id == 0)
  9       {
 10           execlp("ls","ls","-l","-a",NULL);                                                                                                                         
 11           exit(0);
 12       }
 13       return 0;
 14   }
 15 

以上是进程替换的一个代码,我创建的excepro实现了系统的ls -a -l功能

  1. 进程替换不是创建新进程

    • 程序替换(如使用execlexecvexeclpexecvpe等函数)是在现有进程的基础上,用新的程序替换当前进程的代码和数据,而不是创建一个新的进程。
    • 例如,使用execl成功时是没有返回值的,因为当前进程的代码已经被新的程序替换,不会再回到原来的代码执行。
  2. 不同的程序替换函数

    • execv:接受一个字符串数组作为参数,其中第一个元素是要执行的程序的名称,后续元素是程序的参数。
    • execl:接受可变数量的参数,最后一个参数必须是NULL
    • execlp:与execl类似,但会在PATH环境变量中查找要执行的程序,不要求带路径。
    • execvpe:可以传递环境变量,使用全新的环境变量。
  3. 环境变量的处理

    • 子进程默认会继承父进程的全部环境变量。
    • 如果要传递全新的环境变量,可以使用一些方法,如putenvchar*类型的环境变量添加到环境变量表中。
    • 实际上,没有必要专门使用execvpe来传递环境变量,因为putenv等方法可以让子进程继承并修改环境变量。
  4. 程序替换的特点

    • 程序替换不影响命令行参数和环境变量,除非在替换过程中明确修改了它们。
    • 如果程序替换失败,这些函数会返回 -1。

通过对进程的这些方面的理解,我们可以更好地控制程序的执行流程,管理进程的生命周期,以及实现更复杂的程序逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值