函数wait
(1)获取子进程退出状态
(2)回收资源销毁僵尸态子进程
#include <sys/types.h>
#include <wait.h>
int wait(int *status)
函数功能是:父进程一旦调用了wait就立即阻塞自己,由wait分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果只想把这个僵尸进程消灭掉,对这个子进程是如何死掉毫不在意,可以设定这个参数为NULL,pid = wait(NULL);
如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,
如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中, 这是一个整数值(int),指出了子进程是正常退出还是被非正常结束的,以及正常结束时的返回值,或被哪一个信号结束的等信息。用宏来读取
(1,WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。
(2, WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值
子进程中exit(76)进程退出并带回一个状态
(3,WIFSIGNALED(wstatus) 如果子进程被信号终止,则返回true。
(4,WTERMSIG(wstatus)返回导致子进程终止的信号号。
2,函数 waitpid
如果在调用waitpid()函数时,当指定等待的子进程已经停止运行或结束了,则waitpid()会立即返回;但是如果子进程还没有停止运行或结束,则调用waitpid()函数的父进程则会被阻塞,暂停运行。
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能: 等待子进程状态发生变化
参数:pid
pid = -1 //表示等待所有子进程
pid > 0 //表示等待 指定的子进程状态改变
eg:
100 //表示等待pid号为100的子进程状态改变
@wstatus //表示获取到 子进程 状态信息
@options //选项
//可以不阻塞 WNOHANG //hang on
//默认是阻塞 0
wait(&wstatus) <=> waipid(-1,&wstatus,0)
waitpid(-1,&wstatus,WNOHANG); //表示非阻塞调用
非阻塞 和 阻塞
1.阻塞
会父进程处理逻辑
2.非阻塞
父进程 会去查看 子进程状态改变
但是,如果没有发生改变,父进程不阻塞,
整个程序继续往下
非阻塞 必须 套在循环中处理 //轮询
线程 轻量级的进程
线程 成为 CPU执行的最小单位
进程 成为 资源分配的基本单位 (需要大量资源的分配)
线程 : 创建 和 调度 时空开销都比进程小
3. 线程组成
线程tid //thread
程序计数器
寄存器集合
栈
4. 线程与进程的关系
a.线程 是 存在于 进程中的
b.线程 共享了进程的资源 (代码段,数据段,打开一些文件,信号等)
c.线程结束,不一定导致进程结束
创建线程
函数 pthread_create
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
功能:该函数可以创建指定的一个线程。
参数:
@thread 线程id,需要实现定义并由该函数返回。
@attr 线程属性,一般是NULL,表示默认属性。(可结合性+分离属性)
默认(可结合性) -- 自己手动回收
分离属性 -- 系统自动回收
@start_routine -- 线程执行函数 (线程回调函数)
//注: 线程回调函数 --完成线程任务功能的函数
// 需要调用者 自己实现
@arg 回调函数的参数,即参数3的指针函数参数
返回值:成功 0
失败 错误码
注:
1. 主函数所在的执行流 --- 主线程
2. 其它的线程 --- 子线程(次线程)
3. 各个线程间 低位是平等 //对等
函数 pthread_self(); 获得线程tid用%ld打印
在两个线程上对a操作
函数 pthread_exit 退出线程
void pthread_exit(void *retval)
功能: 结束调用的线程
参数:
@retval //退出状态值 //传的是,退出状态值 对应的地址
retval 是void*类型的指针,可以指向任何类型的数据,它指向的数据将作为线程退出时的返回值。如果线程不需要返回任何数据,将 retval 参数置为NULL即可。注意,retval 指针不能指向函数内部的局部数据(比如局部变量)。换句话说,pthread_exit() 函数不能返回一个指向局部数据的指针
注意:
1.pthread_exit 本身表示结束线程
如果用在main函数中 表示结束主线程
主线程结束 并不表示进程结束
主线程执行流结束,进程会在其余线程都结束后结束
d.线程的资源回收
int pthread_join(pthread_t thread, void **retval);
功能:
等待线程结束
参数:
@thread --- 线程tid
@retval --- 用来保存,退出状态值,所在空间的地址
thread 参数用于指定接收哪个线程的返回值;retval 参数表示接收到的返回值,如果 thread 线程没有返回值,又或者我们不需要接收 thread 线程的返回值,可以将 retval 参数置为 NULL。
函数的第2个参数为void**,为二重指针,接收的是线程中函数pthread_exit(void∗retval)的参数可以用来查看pthread_exit传递的参数(如果不关心退出状态,phtread_join的这个参数可以置空,即phtread_ join(tid,NULL), 函数在线程退出时,用来清理线程资源。
返回值:
成功 0
失败 错误码
注:
线程退出时,可以带出退出状态值,
但是传的是,退出状态值对应空间的地址