当前位置: 首页 > news >正文

做印刷品去哪个网站班级优化大师网页版

做印刷品去哪个网站,班级优化大师网页版,建设短视频网站,专业武汉网站建设公司排名目录 0.前言 1. 进程终止 1.1 进程退出的场景 1.2 进程常见退出方法 1.2.1 正常退出 1.2.2 异常退出 2. 进程等待 2.1 进程等待的重要性 2.2 进程等待的方法 2.2.1 wait() 方法 2.2.2 waitpid() 方法 2.3 获取子进程 status 2.4 阻塞等待和非阻塞等待 2.4.1 阻塞等待 2.4.2 非阻…

目录

0.前言

1. 进程终止

1.1 进程退出的场景

1.2 进程常见退出方法

1.2.1 正常退出

1.2.2 异常退出

2. 进程等待

2.1 进程等待的重要性

2.2 进程等待的方法

2.2.1 wait() 方法

2.2.2 waitpid() 方法

2.3 获取子进程 status

2.4 阻塞等待和非阻塞等待

2.4.1 阻塞等待

2.4.2 非阻塞等待

3.结语


(图像由AI生成) 

0.前言

在上一个博客中,我们介绍了如何通过 fork() 函数创建子进程。子进程创建后,通常会执行一些任务,然后终止。而父进程在子进程终止后,需要适当的方式来处理和等待子进程的退出。本文将详细讨论 Linux 中进程的终止与进程等待的相关内容。

1. 进程终止

进程终止是操作系统管理进程生命周期的重要阶段,当进程完成其预定的任务或遇到意外时,它会终止并向系统报告其退出状态。理解进程如何正常或异常终止,对于开发人员和系统管理员进行进程管理至关重要。

1.1 进程退出的场景

进程的退出场景可以大致归纳为以下三种:

  • 代码运行完毕,结果正确:进程执行完所有任务并成功返回预期结果。
  • 代码运行完毕,结果不正确:进程虽然执行结束,但由于逻辑错误或其他原因导致输出结果与预期不符。
  • 代码异常终止:进程在执行过程中发生了未预期的错误,导致进程崩溃或被系统强制终止。

虽然进程退出的原因和场景各异,但所有进程最终都会通过一定的机制向系统报告其结束状态。

1.2 进程常见退出方法

进程退出的方式大致分为两类:正常退出和异常退出。我们可以通过不同的系统调用或外部信号来结束进程。

1.2.1 正常退出

在进程正常退出的情况下,它的生命周期如预期完成,并返回特定的状态码,表示程序执行成功或失败。常见的正常退出方法如下:

  1. main() 函数返回: 在 C/C++ 语言中,进程的入口点是 main() 函数。当程序执行完毕并到达 main() 的结束处,进程会通过 return 语句返回一个状态码,向系统报告其退出状态。典型地,return 0 表示正常退出,而非零值(如 return 1return -1)表示出现了某些错误。

    int main() {// ... 业务逻辑return 0;  // 正常退出
    }
    
  2. 调用 exit()exit()标准库函数,允许程序随时结束执行,并返回状态码。调用 exit() 后,程序会执行清理操作,例如关闭打开的文件、释放资源,并调用通过 atexit() 注册的回调函数。exit() 通常用于程序需要在特定条件下主动退出时。

    #include <stdlib.h>
    int main() {// ... 业务逻辑if (某种错误发生) {exit(1);  // 异常退出}exit(0);  // 正常退出
    }
    
  3. 调用 _exit()_exit()系统调用,通常在子进程中使用。与 exit() 不同,_exit() 不会执行缓冲区的刷新或已注册的清理函数,它直接向内核报告进程结束并释放其资源。通常在子进程完成其工作后,调用 _exit() 立即退出。

    #include <unistd.h>
    int main() {if (fork() == 0) {// 子进程执行_exit(0);  // 立即退出}// 父进程继续执行return 0;
    }
    

1.2.2 异常退出

异常退出是指进程在非预期情况下由于错误或外部干预而终止。常见的异常退出方式包括:

  1. Ctrl+C(信号终止): 当用户在命令行按下 Ctrl+C,系统会发送 SIGINT 信号给进程,指示其立即终止。这是一种外部干预的方式,常用于终止长时间运行的任务。

    ./your_program
    # 用户按下 Ctrl+C,程序收到 SIGINT 信号并终止
    
  2. 异常信号终止: 进程可能由于内部错误(如访问无效内存地址)而收到操作系统发送的异常信号,导致进程非正常退出。常见的异常信号包括 SIGSEGV(段错误)、SIGFPE(算术错误,如除零)等。

    例如,非法内存访问会导致 SIGSEGV 信号:

    int main() {int *ptr = NULL;*ptr = 42;  // 导致段错误,异常退出return 0;
    }
    

当进程因信号终止时,系统会向父进程报告该终止信号,而不是正常的退出状态码。开发者可以通过适当的信号处理机制捕捉并处理这些信号,避免进程非预期崩溃。

2. 进程等待

当子进程终止时,父进程需要进行适当的处理,避免出现僵尸进程。僵尸进程不仅会占用系统的进程表条目,还会导致内存资源无法及时回收。因此,父进程通过进程等待机制来回收子进程资源,并获取子进程的退出状态。

2.1 进程等待的重要性

当子进程结束后,如果父进程不主动等待并回收子进程资源,就可能导致子进程进入僵尸状态。僵尸进程的特性是已经终止,但仍然在系统的进程表中保留一些信息,包括退出状态。由于这些进程已经结束,系统资源无法通过常规的手段释放。

  • 僵尸进程占用系统资源,并且无法被终止。即使使用 kill -9 这样的强制终止信号,也无法“杀死”一个已经处于僵尸状态的进程,因为它已然是“死去的进程”。
  • 另外,父进程往往需要知道子进程任务完成的情况,例如子进程是否正常退出,返回结果是否正确。这些信息对父进程判断后续操作具有重要意义。

因此,父进程通过等待机制能够:

  1. 回收子进程的资源,避免僵尸进程;
  2. 获取子进程的退出状态,了解子进程的执行结果。

2.2 进程等待的方法

Linux 提供了几种等待子进程的方法,最常见的有 wait()waitpid() 函数。

2.2.1 wait() 方法

wait() 是一个简单的进程等待函数,父进程通过调用 wait() 可以阻塞自身,直到有一个子进程终止。它的基本使用方式如下:

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *status);
  • 返回值:成功时,返回已终止的子进程的 PID;如果发生错误,返回 -1
  • 参数
    • status:指向一个整数的指针,用于存储子进程的退出状态。如果不关心子进程的退出状态,可以将该参数设置为 NULL

wait() 函数适用于父进程只需等待任意一个子进程退出的场景。当父进程有多个子进程时,wait() 将会等待其中的任何一个结束,并返回它的进程 ID。

2.2.2 waitpid() 方法

waitpid()wait() 的增强版本,提供了更多的功能和灵活性。例如,父进程可以通过 waitpid() 等待特定的子进程,或者选择非阻塞等待。其函数定义如下:

pid_t waitpid(pid_t pid, int *status, int options);
  • 返回值

    • 如果成功,waitpid() 返回终止的子进程的 PID。
    • 如果设置了 WNOHANG 选项且没有任何子进程终止,返回 0
    • 如果发生错误,返回 -1,并设置 errno 以指示错误原因。
  • 参数

    • pid
      • pid = -1:等待任意子进程终止,功能与 wait() 相同。
      • pid > 0:等待指定 PID 的子进程终止。
    • status:与 wait() 中类似,保存子进程的退出状态。可以通过 WIFEXITED(status) 判断子进程是否正常终止,使用 WEXITSTATUS(status) 提取退出码。
    • options
      • WNOHANG:如果没有子进程终止,则 waitpid() 立即返回,而不会阻塞父进程。这对于父进程需要同时处理其他任务时非常有用。

2.3 获取子进程 status

在使用 wait()waitpid() 等待子进程时,除了能够回收子进程的资源,还可以通过 status 参数获取子进程的退出信息。这个参数是一个输出型参数,由操作系统填充,用来向父进程反馈子进程的退出状态。

status 参数的使用

  • status 的意义: 当我们调用 wait()waitpid() 时,status 参数是一个用于存储子进程退出状态的变量。如果我们不关心子进程的退出状态,可以将这个参数设置为 NULL。然而,如果我们希望获得子进程的退出信息,需要提供一个指针,操作系统会将退出信息写入该地址。

  • 位图解读status 参数并不是一个简单的整形值,而是一个位图,通常我们只需要关心它的低 16 位。其中,最常用的信息包括:

    • 子进程是否正常退出;
    • 子进程的退出码;
    • 如果是异常终止,是什么信号导致的异常终止。

当子进程正常退出时,status 中的高位(第 8 到第 15 位)存储了子进程的退出码,而低 7 位(第 0 到第 6 位)用于表示子进程的信号终止信息。

  • 正常退出:如果子进程是通过 exit()return 正常退出,status 的低 7 位应该是 0,表示没有通过信号终止。此时,高位存储的是子进程的退出码,可以通过 st >> 8 提取。

  • 异常终止:如果子进程因为信号而被终止,低 7 位会存储导致终止的信号编号。父进程可以通过 st & 0X7F 获取到信号编号,进一步判断子进程因何信号终止。

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main() {pid_t pid;if ( (pid=fork()) == -1 ) {perror("fork"), exit(1);}if (pid == 0) {// 子进程休眠20秒后正常退出,退出码为10sleep(20);exit(10);} else {// 父进程等待子进程退出int st;int ret = wait(&st);if (ret > 0 && (st & 0X7F) == 0) { // 正常退出printf("child exit code:%d\n", (st >> 8) & 0XFF);} else if (ret > 0) { // 异常退出printf("sig code : %d\n", st & 0X7F);}}
}

测试结果

  1. 当子进程正常退出时,输出如下:

     

    子进程正常退出,父进程通过 status 获取子进程的退出码为 10

  2. 当子进程在其他终端被 kill 掉时,输出如下:

     

    这是因为子进程被 SIGKILL 信号(编号为 9)终止,父进程通过 status 获取到了导致子进程终止的信号编号。

2.4 阻塞等待和非阻塞等待

在进程等待时,父进程可以选择采用阻塞等待或者非阻塞等待的方式来处理子进程的退出。阻塞等待会使父进程在子进程退出前一直处于等待状态,而非阻塞等待则允许父进程在子进程未退出时继续执行其他任务。

2.4.1 阻塞等待

阻塞等待是最常见的等待方式。当父进程调用 wait()waitpid() 并不设置任何非阻塞选项时,父进程会一直等待直到有子进程退出。此时,父进程会被阻塞,无法进行其他操作。

代码示例

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {pid_t pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");exit(1);}if (pid == 0) {  // 子进程printf("Child process running...\n");sleep(5);  // 子进程休眠5秒模拟任务执行printf("Child process finished.\n");exit(0);} else {  // 父进程int status;printf("Parent waiting for child to exit (blocking)...\n");wait(&status);  // 阻塞等待子进程结束printf("Child exited with status: %d\n", WEXITSTATUS(status));}return 0;
}

输出结果

  • 父进程在子进程运行期间被阻塞,直到子进程结束后才继续执行。
 

2.4.2 非阻塞等待

非阻塞等待允许父进程在等待子进程时继续执行其他任务,而不是阻塞等待子进程结束。通过在 waitpid() 中传入 WNOHANG 选项,父进程可以立即返回,即使子进程还没有结束。

代码示例

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {pid_t pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");exit(1);}if (pid == 0) {  // 子进程printf("Child process running...\n");sleep(5);  // 子进程休眠5秒模拟任务执行printf("Child process finished.\n");exit(0);} else {  // 父进程int status;printf("Parent checking child status (non-blocking)...\n");while (1) {pid_t result = waitpid(pid, &status, WNOHANG);  // 非阻塞等待if (result == 0) {// 子进程还没有结束printf("Child process is still running...\n");sleep(1);  // 父进程继续执行其他任务} else if (result == -1) {perror("waitpid failed");exit(1);} else {// 子进程结束printf("Child exited with status: %d\n", WEXITSTATUS(status));break;}}}return 0;
}

输出结果

  • 父进程每隔 1 秒检查一次子进程状态,而不会阻塞自己等待子进程结束。当子进程结束时,父进程获取子进程的退出状态并结束循环。

3.结语

Linux 系统中的进程终止和进程等待是进程管理中的核心内容。通过合理地终止进程并及时进行等待操作,父进程可以有效地处理子进程的退出,避免产生僵尸进程,同时保证系统资源的高效利用。希望通过本文的讲解,读者能够对进程终止和进程等待有更深入的理解。


文章转载自:
http://lean.ddfp.cn
http://coldbloodedly.ddfp.cn
http://chastening.ddfp.cn
http://neocolonial.ddfp.cn
http://bazoom.ddfp.cn
http://saltwater.ddfp.cn
http://insititious.ddfp.cn
http://honied.ddfp.cn
http://monosabio.ddfp.cn
http://tailorship.ddfp.cn
http://apocatastasis.ddfp.cn
http://censer.ddfp.cn
http://strad.ddfp.cn
http://rhatany.ddfp.cn
http://chubby.ddfp.cn
http://unix.ddfp.cn
http://ablatival.ddfp.cn
http://pretensive.ddfp.cn
http://gnar.ddfp.cn
http://tandjungpriok.ddfp.cn
http://abortionism.ddfp.cn
http://disadvantaged.ddfp.cn
http://justus.ddfp.cn
http://philharmonic.ddfp.cn
http://poikilocyte.ddfp.cn
http://nova.ddfp.cn
http://toastmaster.ddfp.cn
http://corslet.ddfp.cn
http://mamillated.ddfp.cn
http://pooch.ddfp.cn
http://decelerate.ddfp.cn
http://bantam.ddfp.cn
http://uneda.ddfp.cn
http://gallery.ddfp.cn
http://electrotechnician.ddfp.cn
http://joannes.ddfp.cn
http://knotting.ddfp.cn
http://swingtree.ddfp.cn
http://spelean.ddfp.cn
http://dey.ddfp.cn
http://microcode.ddfp.cn
http://outcry.ddfp.cn
http://disseize.ddfp.cn
http://celesta.ddfp.cn
http://digamy.ddfp.cn
http://exsufflation.ddfp.cn
http://impressure.ddfp.cn
http://tuitional.ddfp.cn
http://thionate.ddfp.cn
http://matriarch.ddfp.cn
http://britisher.ddfp.cn
http://syllogise.ddfp.cn
http://agist.ddfp.cn
http://oki.ddfp.cn
http://flavodoxin.ddfp.cn
http://neurular.ddfp.cn
http://daddy.ddfp.cn
http://greengrocer.ddfp.cn
http://phantomlike.ddfp.cn
http://vysotskite.ddfp.cn
http://negative.ddfp.cn
http://salvation.ddfp.cn
http://doeth.ddfp.cn
http://actigraph.ddfp.cn
http://skittle.ddfp.cn
http://contain.ddfp.cn
http://callet.ddfp.cn
http://dressage.ddfp.cn
http://reinforcer.ddfp.cn
http://patella.ddfp.cn
http://dapple.ddfp.cn
http://jailbreak.ddfp.cn
http://plicated.ddfp.cn
http://profit.ddfp.cn
http://misalignment.ddfp.cn
http://ascigerous.ddfp.cn
http://arjuna.ddfp.cn
http://chrematistic.ddfp.cn
http://tamable.ddfp.cn
http://submandibular.ddfp.cn
http://cheapie.ddfp.cn
http://gabionade.ddfp.cn
http://unconversant.ddfp.cn
http://remigrant.ddfp.cn
http://antibiotics.ddfp.cn
http://technosphere.ddfp.cn
http://rutabaga.ddfp.cn
http://tenace.ddfp.cn
http://basseterre.ddfp.cn
http://flattish.ddfp.cn
http://sunspot.ddfp.cn
http://wreathen.ddfp.cn
http://bfr.ddfp.cn
http://rhizophoraceous.ddfp.cn
http://floss.ddfp.cn
http://andromache.ddfp.cn
http://photoelement.ddfp.cn
http://unspoken.ddfp.cn
http://orthokeratology.ddfp.cn
http://cotics.ddfp.cn
http://www.hrbkazy.com/news/66588.html

相关文章:

  • 中国黄金集团j建设公司网站潍坊网站关键词推广
  • 建站之星免费唐山seo优化
  • 绍兴市住房与城乡建设厅网站女教师遭网课入侵直播录屏曝光se
  • 深圳机票网站建设互联网营销是什么意思
  • 购物网站开发vue seo 优化方案
  • 建筑公司有哪些国内seo公司排名
  • 广东中山网站建设武汉seo关键词排名
  • 自己编辑网站怎么做的app怎么推广
  • 东莞网络推广公司旧版优化大师
  • 网站logo在哪里汕头自动seo
  • wordpress别名404上海seo外包
  • wordpress中常用插件安装谷歌seo排名技巧
  • 外国优秀网站设计宁波seo自然优化技术
  • 微网站需要备案吗培训心得简短200字
  • 沧州网络运营中心seo排名培训公司
  • 哪些网站可以找到做药人的信息怎样在百度上做广告
  • 外贸公司网站如何做网上推广网络销售平台上市公司有哪些
  • 免费做爰小说网站百度收录网站需要多久
  • 做网站学的是代码吗南宁seo专员
  • php网站开发专业介绍seo服务公司上海
  • 东莞多语言网站建设百度seo公司兴田德润
  • 如何做网站架构手机软文广告300字
  • 图文排版设计济南seo关键词优化方案
  • 海口可信的海南网站建设学seo需要学什么专业
  • 如何建设手机网站国际站seo优化是什么意思
  • 怎么自己做论坛网站互联网广告代理加盟
  • 网站的在线qq客服链接怎么做的百度站长工具添加不了站点
  • 设计做图免费网站2000元代理微信朋友圈广告
  • 北京网站的建立公司网页制作流程
  • wordpress实现mp4播放器seo网站建设是什么意思