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

day28:零基础学嵌入式之进程2

1.进程的退出

僵尸进程和孤儿进程

僵尸进程:进程执行结束但空间未被回收变成僵尸进程;

孤儿进程:父子进程中,父进程先消亡,子进程就变成孤儿进程,该子进程就向上找结点,它的父进程发生变化;

2.exit   void exit(int status) 


        (1)  库函数,退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,负进程都能使用wait,waitpid获得这个状态,以及资源的回收。

  •         exit(1);(全面回收工作,文件关闭,堆释放,缓冲区的清理)

(2)功能:让进程退出,并刷新缓存区
(3)参数:status:进程退出的状态(正常退出括号内写0,非正常退出(异常终止),传1)
(4)返回值:缺省

EXIT_SUCCESS 0
EXIT_FAILURE 1

#include <stdio.h>
#include <stdlib.h>
int	main(int argc, char **argv)
{printf("made in china\n");exit(0);printf("aaaaa\n");return 0;
}


(4)return  当该关键字出现在main函数中时候可以结束进程,如果在其他函数中则表示结束该函数。

  • exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit

3._exit    系统调用:void _exit(int status);


(1)功能:让进程退出,不刷新缓存区
(2)参数:status:进程退出状态
(3)返回值:缺省

mian(int agc,argv)
{
        main();
}  

回调函数:某个条件满足时,自动触发

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int	main(int argc, char **argv)
{printf("made in china\n");_exit(1);printf("aaaaa\n");return 0;
}

4.atexit:int atexit(void (*function)(void));


(1)功能:注册进程正常退出前执行的函数(触发条件);括号内的函数指针,只有条件触发才被动调用
(2)参数:function:函数指针:指向void返回值void参数的函数指针;
(3)返回值:成功返回0,失败返回非0;
(4)当程序调用exit或者由main函数执行return时,所有用atexit,注册的退出函数,将会由注册时顺序倒序被调用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *p;
void clean(void)
{printf("was clean:%s\n",p);free(p);
}
int	main(int argc, char **argv)
{p = malloc(32);atexit(clean);strcpy(p, "hello");printf("aaaaaaaaaaa");exit(1);return 0;
}

5.进程空间的随机回收:pid_t wait(int *status);

  • eg:exit(20);
  • wait/waitpid

为什么要回收:pcb块太多,占了很多内核空间,时间久了会崩溃
(1)功能:该函数可以阻塞等待任意子进程退出,并回收该进程的状态。一般用于父进程回收子进程状态;
(2)参数:status 进程退出时候的状态
  如果不关心其退出状态一般用NULL表示
  如果要回收进程退出状态,则用WEXITSTATUS回收。

(3)返回值:成功 回收的子进程pid,失败 -1;

#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
//括号内空指针
int	main(int argc, char **argv)
{pid_t pid = fork();if(pid>0){printf("father:    pid: %d\n",getpid());pid_t vel =wait(NULL);printf("pid:%d   ,vel :%d\n",pid,vel);}else if (0==pid ){int i = 4;while (--i) {printf("child   pid:%d\n",getpid());}}else {perror("pid");exit(1);}return 0;
}
//传参的
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>int	main(int argc, char **argv)
{pid_t pid = fork();if(pid>0){printf("father:    pid: %d\n",getpid());int status;pid_t vel = wait(&status);if(WIFEXITED(status)){printf("the chile terminated normally ,exit value :%d",WEXITSTATUS(status));}else if(WIFSIGNALED(status)){printf("the chile  was terminated by sigal ,exit valu:%d",WTERMSIG(status));}printf("pid:%d   ,vel :%d\n",pid,vel);}else if (0==pid ){int i = 15;while (--i) {printf("child   pid:%d\n",getpid());sleep(1);}}else {perror("pid");exit(20);}return 0;
}
  • WIFEXITED(status)  是不是正常结束
  • WEXITSTATUS(status) 正常结束后,使用这个宏去那返回值
  • WIFSIGNALED(status) 是不是收到了信号而终止的
  • WTERMSIG(status)如果是信号终止的,那么是几号信号。

6.指定空间子进程回收pid_t wait(int *status);


1)如果所有的子进程都在运行,在阻塞
2)如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返回。
3)如果没有子进程,则立即出错退出。

(1)waitpid(-1,status,0)=wait(status);
        pid_t waitpid(pid_t pid, int *status, int options);
        < -1 回收指定进程组内的任意子进程
        -1 回收任意子进程,组内外
        0 回收和当前调用waitpid一个组的所有子进程,组内
        > 0 回收指定ID的子进程
         waitpid (-1,a,0)  == wait(a);
 status 子进程退出时候的状态,
   如果不关注退出状态用NULL;
  options 选项:
   0  表示回收过程会阻塞等待
WNOHANG 表示非阻塞模式回收资源。(这事儿办不了,先办后面的,这个一般套在循环中)
返回值:成功 返回接收资源的子进程pid,失败  -1,0,

#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>int	main(int argc, char **argv)
{pid_t pid = fork();if(pid>0){printf("father: pid: %d\n",getpid());int status;while(1){pid_t vel = waitpid(pid,&status,WNOHANG);//阻塞 blockif(vel == pid)//回收成功{if(WIFEXITED(status))//子进程正常结束{printf("the child terminated normally ,exit value :%d\n",WEXITSTATUS(status));}else if(WIFSIGNALED(status))//{printf("the child  was terminated by singal ,exit value :%d\n",WTERMSIG(status));}   printf("pid:%d   ,vel :%d\n",pid,vel);break;}else if(0 == vel){printf("回收失败!\n");}else {printf("错误回收!\n");return 1;}}}else if (0==pid ){int i = 2;while (--i) {printf("child   pid:%d\n",getpid());sleep(1);}}else {perror("pid");exit(20);}return 0;
}
  • whereis    :查看系统上 ***有没有装上
  • echo $PATH:显示的系统路径
  • env:显示环境变量;

execute
7.exec族


(1)用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。其实有六种以exec开头的函数,常用4种统称exec函数:

(2)execl:int execl(const char *path, const char *arg, ...
                       /* (char  *) NULL */);

#include <stdio.h>
#include <sys/sysmacros.h>
#include <unistd.h>
int	main(int argc, char **argv)
{// execl("/bin/ls", "ls","-l","-a","--color=never",NULL);// printf("safagvada");// execl("/usr/bin/firefox", "firefox","www.baidu.com",NULL);// execl("/bin/pwd", "pwd",NULL);return 0;
}


 

(3)execlp: int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);

#include <stdio.h>
#include <sys/sysmacros.h>
#include <unistd.h>
int	main(int argc, char **argv)
{// execlp("ls", "ls","-l","-a","--color=auto",NULL);//execlp("cat", "cat","./01fock.c",NULL);// execlp("./app", "./a.out",NULL);char *args[]= {"./a.out",NULL};char *argn[]={"ls","-l","-a","--color=auto",NULL};// execv("./app",args);execvp("./app", args);return 0;
}

(4)execv: int execv(const char *path, char *const argv[]);

#include <stdio.h>
#include <sys/sysmacros.h>
#include <unistd.h>
int	main(int argc, char **argv)
{char *args[]= {"./a.out",NULL};char *argn[]={"ls","-l","-a","--color=auto",NULL};execv("./app",args);return 0;
}

(5)execvp:  int execvp(const char *file, char *const argv[]);

#include <stdio.h>
#include <sys/sysmacros.h>
#include <unistd.h>
int	main(int argc, char **argv)
{char *args[]= {"./a.out",NULL};char *argn[]={"ls","-l","-a","--color=auto",NULL};execvp("./app", args);return 0;
}

8.sysem:int system(const char *command); 

(1)system("vim 1.c");

        原理:fork+exec 
(2)功能:使用该函数可以将shell命令直接在代码中执行。
(3)参数:command要执行的shell命令

(4)返回值:成功 0,失败 -1

http://www.xdnf.cn/news/663769.html

相关文章:

  • MQTT通信协议
  • [面试精选] 0076. 最小覆盖子串
  • Linux多线程(二)之进程vs线程
  • Cell Metab.|复旦大学储以微、骆菲菲团队:Foxp3改造CAR-T,从「能量危机」到「代谢续航」的实体瘤治疗新路径
  • Android GPU Inspector深度解析:从零掌握驱动级性能数据抓取与优化
  • FastAPI 中间件
  • 电子标签倒计时应用
  • 从自发到赋能:产品经理的成长与 AI 时代的自我重塑
  • 测试W5500的第7步_使用ioLibrary库创建HTTP客户端
  • Linux中SHELL脚本常用命令
  • 安卓实用复制功能增强工具
  • 【杂谈】STM32使用快速傅里叶变换库函数后如何比较准确地找到n次谐波幅值
  • Python不要使用可变对象作为函数的默认参数
  • 记忆术-拼音字母形象法【针对“音形义“里谐音法的补充记忆法】
  • 布局泰国遇网络难题?中泰跨境网络组网专线成破局关键
  • Unity中的文件读写TXT 与XML
  • java中的线程安全的集合
  • 如何用DeepSeek修改论文,防止AI幻觉?
  • 题目 3331: 蓝桥杯2025年第十六届省赛真题-LQ 图形
  • 【Axure结合Echarts绘制图表】
  • 华为OD机试_2025 B卷_返回矩阵中非1的元素个数(Python,100分)(附详细解题思路)
  • Python应用“面向对象”小练习
  • 【深度学习】4. 参数初始化详解与数学推导: Xavier, He
  • 敦普水性双组份聚氨酯面漆检验报告(SGS、重金属含量、低voc)
  • 电路中常见器件及作用(电阻 电容 电感)
  • 如何通过PHPMyadmin对MYSQL数据库进行管理?
  • IP离线库与网站集成
  • 如何在 Windows 10 PC 上获取 iPhone短信
  • MS1205N激光测距用高精度时间测量(TDC)电路
  • 火山引擎云服务器带宽支持