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

Linux软件编程-进程(2)及线程(1)

1.进程回收资源空间

(1)wait函数

头文件:

       #include <sys/types.h>
#include <sys/wait.h>

函数接口:

       pid_t wait(int *wstatus);
功能:阻塞等待回收子进程的资源空间
参数:
wstatus :保存子进程消亡状态的变量地址
NULL:不保存子进程退出的状态
返回值:
成功:返回回收到的子进程的PID号
失败:-1
wait(NULL);

基本思想:

进程同步:允许父进程暂停执行,直到其子进程终止或改变状态

资源回收:确保子进程终止后其资源被正确释放(防止"僵尸进程")

状态获取:让父进程能够获取子进程的退出状态信息

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{int *p = malloc(sizeof(int));*p = 100;pid_t pid = fork();if(pid > 0){int wstatus;pid_t pidtmp = wait(NULL);printf("pidtmp = %d\n", pidtmp);/*if (WIFEXITED(wstatus)){printf("%d over normall, state : %d\n", pidtmp, WEXITSTATUS(wstatus));}else if (WIFSIGNALED(wstatus)){printf("%d ober by signal,signal num = %d\n", pidtmp, WTERMSIG(wstatus));}*/while(1){printf("ppid = %d, pid = %d, *p = %d\n",getpid(), pid, *p);sleep(1);}}else if(0 == pid){    int i = 10;while(i--){printf("pid = %d, ppid = %d, *p = %d\n", getpid(), getppid(), *p);sleep(1);}}else{perror("fork error");exit(0);}return 0;
}

(2)waitpid函数

搭配轮询回收

函数接口:

pid_t waitpid(pid_t pid, int *status, int options);
   功能:回收指定进程的资源
和wait功能相似,比wait更灵活
 参数:
pid:
<-1 回收指定进程组内的任意子进程 (-100.等待GID=100的进程组中的任意子进程)
-1 回收任意子进程,组内外
0 回收和当前调用waitpid一个组的所有子进程,组内 
> 0 回收指定ID的子进程
status 子进程退出时候的状态,
如果不关注退出状态用NULL;
options 选项:
0  表示回收过程会阻塞等待
WNOHANG 表示非阻塞模式回收资源。
   返回值:

            成功 返回接收资源的子进程pid
失败  -1
设定为非阻塞且没有回收到子进程返回0 

(3)子进程资源空间回收策略

1. wait阻塞回收:一般情况下,父进程专门负责资源回收;
2. waitpid非阻塞方式回收:搭配轮询方式回收。
3. 不回收:子进程的任务需要一直执行
4. 异步回收:当子进程结束时通知父进程进行回收

2.  exec : 函数族

(1)基本概念

在一个进程里面执行另外一个文件(可执行文件):
本质:将文本去的指令代码替换成exec要执行的文件的指令。

算法思想:

 

不创建新进程:

与 fork() 不同,exec 不会创建新进程,只是替换当前进程的内容

参数传递多样性:

列表形式(execl, execlp, execle):以 NULL 结尾的可变参数列表

数组形式(execv, execvp, execvpe):通过字符串数组传递参数

函数关键特点
execl路径+参数列表形式,需要完整路径
execlp文件名+参数列表形式,会在 PATH 环境变量中查找可执行文件
execle路径+参数列表+自定义环境变量形式
execv路径+参数数组形式,需要完整路径
execvp文件名+参数数组形式,会在 PATH 环境变量中查找可执行文件
execvpe文件名+参数数组+自定义环境变量形式

(2)函数接口

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

path:要执行的可执行文件的路径和名称
arg:执行该可执行文件时需要传递的参数
NULL :参数传递结束标志
返回值:
出错:-1

 int execlp(const char *file, const char *arg, ...   /* (char  *) NULL */);
功能:
从PATH指定的系统路径下寻找该可执行文件
参数:
file:需要执行的可执行文件的名称(系统路径下已有的文件)
arg : 执行该可执行文件时需要传递的参数

       int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

 

l:list  列表
p:path  路径 : 系统路径
v:vector 容器
e:env  环境变量

 

#include <stdio.h>
#include <unistd.h>int main(int argc, char const *argv[])
{//execl("/usr/bin/pstree", "pstree", "-p", NULL);char *arg[] = {"ls", "-l", NULL};//execv("/bin/ls", arg);//execlp("ls", "ls", "-l", NULL);execvp("ls", arg);return 0;
}

3.system函数

system 通过 fork-exec 启动 shell 来执行命令(支持管道/重定向等 shell 特性),并自动处理进程等待和信号,返回命令的退出状态;而 exec 直接替换当前进程为指定程序(不启动 shell,无返回),需配合 fork 使用并手动管理子进程。

 

与exec函数族关键区别:

shell 处理:system 调用 /bin/sh 解析命令,exec 直接执行程序。

进程控制:system 阻塞等待命令完成,exec 替换当前进程(若成功则不返回)。

返回值:system 返回命令状态,exec 仅在失败时返回(成功则执行新程序)。

使用场景:system 适合简单命令调用,exec 适合精确控制进程替换。

用execl函数实现system函数

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{pid_t pid = fork();if(pid > 0){printf("pid = %d",getpid());}else if(0 == pid){    printf("pid = %d\n", getpid());execl("/bin/ls", "ls", "-l", NULL);}else{perror("fork error");exit(0);}pid_t pidtmp = wait(NULL);printf("pidtmp = %d\n", pidtmp);return 0;
}

4.线程的基本概念

1. 什么是线程
轻量级的进程,可实现多任务的并发。
进程是操作系统资源分配的最小单位;
线程是操作系统任务调度的最小单位。    
2. 线程的创建
线程由某个进程创建。
进程创建线程时,会为其分配独立的(8M)栈区空间;
线程和所在进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。

3. 线程的调度
宏观并行,微观串行     

4. 线程消亡
1.  线程退出
2. 回收线程资源空间

5.进程与线程的区别

进程:

           进程是操作系统资源分配的最小单位;
资源消耗:进程资源开销大,每次创建都需要有0-4G的虚拟内存空间   
效率角度:由操作系统创建,创建时耗时比线程大;跨进程调度比跨线程调度慢;
通信方面: 进程间不能直接通信,需要使用进程间通信机制(IPC机制)
安全性角度:进程安全性比线程高,各进程空间独立

     

线程:

              线程是操作系统任务调度的最小单位。
资源消耗:资源开销较小,只需要所在进程为其开辟8M的栈区空间
效率角度:由所在进程创建;跨进程调度比跨线程调度慢;
通信方面:通信简单,可以使用线程共享的区域进行通信(比如全局变量)
安全性角度:线程没有进程安全性好,一个线程异常可能影响同一进程中的所有线程

6.线程的相关编程

(1)线程的创建

头文件:

            #include <pthread.h>

函数接口:

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
功能:创建一个新的线程
  参数:
thread : 保存线程ID的变量地址
attr:线程属性的对象地址
NULL : 按照默认属性创建
start_routine:函数的指针:指向线程启动后要执行的任务(线程任务函数)
arg:为线程任务函数传递的参数
     返回值:
成功:0
失败:非0

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *tash(void *arg)
{printf("tid = %ld\n", pthread_self());
}int main(int argc, char const *argv[])
{pthread_t tid;int ret = pthread_create(&tid, NULL, tash, NULL);if(ret != 0){printf("pthread create error\n");return -1;}sleep(2);return 0;
}

 

 

http://www.lryc.cn/news/622290.html

相关文章:

  • TDengine IDMP 高级功能(2. 事件模板)
  • 低资源语言翻译:数据增强与跨语言迁移学习策略
  • 第二十四天:虚函数与纯虚函数
  • 订单状态定时处理(Spring Task 定时任务)
  • OpenTelemetry WebSocket 监控终极方案:打通最后一公里
  • liteflow
  • kubernetes(4) 微服务
  • C#文件复制异常深度剖析:解决“未能找到文件“之谜
  • 大白话解析 Solidity 中的防重放参数
  • 大白话解析 Solidity 中的数据位置关键字 memory
  • [激光原理与应用-284]:理论 - 波动光学 - 无线电波,无线通信的频谱
  • 人工智能与社会治理:从工具到生态的范式重构
  • 数据民主化×智能进阶化:AI+BI不可逆的决策革命已至
  • Python 高级语法与用法详解 —— 提升编程效率与代码质量
  • JUC LongAdder并发计数器设计
  • Manus AI与多语言手写识别
  • 项目生命周期
  • stream流debug
  • 源码分析mcp定义tools映射到LLM输入的过程
  • L4 级别自动驾驶 软件架构设计
  • Midjourney绘画创作入门操作
  • 二十四、Mybatis-基础操作-删除(预编译SQL)
  • 什么是可信空间的全域节点、区域节点、业务节点?
  • 基于STM32与边缘计算的工业设备异常振动预警系统设计
  • Pytest 插件使用指南:让你的测试更高效
  • 深度解读 Browser-Use:让 AI 驱动浏览器自动化成为可能
  • 如何回答研究过MQ的源码吗
  • week1-[顺序结构]大海
  • Centos7 服务管理
  • SpatialVLM和SpatialRGPT论文解读