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;
}
评论前必须登录!
注册