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

Linux系统——进程与线程

一、回收资源空间

pid_t wait(int *wstatus);

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

【wait(NULL)】

    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 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main(int argc, const char *argv[])
{pid_t pid = fork();if (pid > 0){while (1){int wstatus;//pid_t pidtmp = waitpid(-1, &wstatus, 0);  ==>wait(&wstatus)pid_t pidtmp = waitpid(-1, &wstatus, WNOHANG);printf("pidtmp = %d\n", pidtmp);if (0 != 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));}}printf("I am father : pid= %d\n", getpid());sleep(1);}}else if (0 == pid){int i = 20;while (i--){printf("I am son : pid = %d\n", getpid());sleep(1);}exit(9);//return 9;}else{perror("fork error");}return 0;

二、子进程资源回收策略

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

三、exec函数族

       在一个进程里面执行另外一个文件(可执行文件):
本质:将文本去的指令代码替换成exec要执行的文件的指令。
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  环境变量

在同一目录下,创建一个hello.c文件,在其编写打印出“hello world”字符串的代码,运行后生成可执行文件hello

创建exec.c文件,使运行exec.c文件而执行hello.c

int main(int argc, const char *argv[])
{printf("exec : pid = %d\n", getpid());execl("./hello", "./hello", NULL);printf("after exec\n");return 0;
}

注:使用exec函数,他不会在自己的 .c 中结束,而是在hello.c中结束,也就是在子进程中结束,再就是说  printf("after exec\n");

这行代码并不会执行,如过要返回父进程中结束,需要用下面介绍的函数。

四、system函数

int main(int argc, const char *argv[])
{printf("system : pid = %d\n", getpid());system("./hello");printf("After system\n");return 0;
}

其参数,是需要执行其他可执行文件的地址

手撕system函数

int my_system(char *buff)
{char *arg[10] = {NULL};int i = 0;char cmd[512] = {0};strcpy(cmd, buff);arg[i] = strtok(cmd, " ");while (arg[i] != NULL){printf("arg[%d] = %s\n", i, arg[i]);i++;arg[i] = strtok(NULL, " ");}pid_t pid = fork();if (pid > 0){wait(NULL);}else if (0 == pid){execvp(arg[0], arg);}return 0;}int main(int argc, const char *argv[])
{printf("system : pid = %d\n", getpid());
//	system("./hello");my_system("ls -l");printf("After system\n");return 0;
}

(srctok函数在之前文章有介绍,需要自行搜索)

五、线程

1. 什么是线程

轻量级的进程,可实现多任务的并发。
进程是操作系统资源分配的最小单位;
线程是操作系统任务调度的最小单位。

2. 线程的创建

线程由某个进程创建。
进程创建线程时,会为其分配独立的(8M)栈区空间;
线程和所在进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。

3. 线程的调度

宏观并行,微观串行     

4. 线程消亡

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

5. 进程和线程的区别


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

     

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

6.线程的相关编程

     1. 线程的创建: pthread_create()
pthread_self():获取当前线程的ID号
2. 线程调度:由操作系统调度
3. 线程消亡: 
1. 线程退出:pthread_exit();
2. 线程回收:pthread_join();

       #include <pthread.h>

(注:线程函数库是由Linux系统向RedHat公司引入,并不属于Linux,也就是在编译时,需要加上  - pthread/-lpthread)

       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 *task(void *arg)
{printf("I am thread : tid = %ld\n", pthread_self());
}int main(int argc, const char *argv[])
{//主进程、主线程pthread_t tid;int ret = pthread_create(&tid, NULL, task, NULL);if (ret !=0){printf("pthread_create error\n");return -1;}while (1){}return 0;

代码运行速度较快,可能导致task函数没有执行,就导致运行结束,所以加个死循环,手动停止,或者将其更改为

sleep(2)

http://www.dtcms.com/a/333129.html

相关文章:

  • PyTorch 进行人脸训练和 Java 实现人脸识别的解决方案
  • 权重迁移笔记
  • Android RxJava 过滤与条件操作详解
  • CPU性能篇-系统的软中断CPU使用率升高如何处理-Day 06
  • Pytest项目_day16(yaml和parametrize结合)
  • 【R语言】更换电脑后,如何在新设备上快速下载原来设备的 R 包?
  • 神经网络、深度学习与自然语言处理
  • Linux程序内存布局分析
  • ROS2 setup.bash和setup.sh区别差异
  • 【JAVA】实现word添加标签实现系统自动填入字段
  • Python匿名函数的具体用法
  • 堕落之主 单机+联机 全DLC 送修改器(Lords of the Fallen)免安装中文版
  • 【机器人-基础知识】ROS常见功能架构
  • 【JAVA高级】实现word转pdf 实现,源码概述。深坑总结
  • JavaScript(JS)DOM(四)
  • 提词器电脑版哪个好用?芦笋提词器优势评测与下载
  • 算法02 二进制与位运算
  • 解锁AI大模型:Prompt工程全面解析
  • 迭代器模式C++
  • Unity中 terriaria草,在摄像机拉远的时候就看不见了,该怎么解决
  • week1-[循环嵌套]蛇
  • 低资源语言翻译:数据增强与跨语言迁移学习策略
  • git疑问,暂时记录
  • “降碳30%+节能25%,园区智慧能源管理系统重塑示范园区竞争力
  • Flutter Form组件的基本使用
  • 【Python办公】Excel转json(极速版)-可自定义累加字段(如有重复KEY)
  • 力扣top100(day04-06)--贪心算法
  • LeetCode 53.最大子数组和:贪心算法下的连续子数组最优解
  • Android项目中Ktor的引入与使用实践
  • mlir clone