一、wait(阻塞调用) pid_t wait(int *status);
1.功能:(1)获取子进程退出状态 (2).回收资源 //会让僵尸态的子进程销毁
参数
int *status
: 指向一个整数的指针,wait
会通过这个指针返回子进程的状态信息。如果不关心状态信息,可以将其设置为NULL
。
返回值
- 如果成功,返回结束的子进程的进程 ID。
- 如果没有子进程可等待或发生错误,返回
-1
,并设置errno
。
状态信息
通过传递给 status
的值,父进程可以使用一些宏来解析子进程的状态:
WIFEXITED(status)
: 如果子进程正常结束,返回非零值。WEXITSTATUS(status)
: 如果子进程正常结束,返回其退出状态。WIFSIGNALED(status)
: 如果子进程因信号而结束,返回非零值。WTERMSIG(status)
: 返回导致子进程终止的信号编号。
2.父进程要获得子进程的退出状态
子进程
exit(退出状态值)
退出状态值 只有最低8位有效 [0~255]
父进程
wait(&status)
获取到退出状态值
WIFEXITED() //先判断是否为正常退出
WEXITSTATUS() //获取到exit传递的退出状态值
示例:
二、waitpid(可以非阻塞调用)
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:
等待子进程状态发生变化
参数
-
pid_t pid
: 要等待的子进程的进程 ID(PID)。- 如果
pid
为 -1,等待任何一个子进程。 - 如果
pid
大于 0,等待具有指定 PID 的子进程。 - 如果
pid
小于 -1,等待进程组 ID 等于|pid|
的任何子进程。
- 如果
-
int *status
: 指向一个整数的指针,用于存放子进程的状态信息。如果不关心,可以设置为NULL
。 -
int options
: 通常为 0,或者可以设置如WNOHANG
(非阻塞等待)等选项。
返回值
- 如果成功,返回结束的子进程的进程 ID。
- 如果没有该子进程,返回
0
(在使用WNOHANG
时)。 - 如果出错,返回
-1
,并设置errno
。
状态信息
与 wait
一样,可以使用一些宏来解析状态信息,例如:
WIFEXITED(status)
: 子进程是否正常结束。WEXITSTATUS(status)
: 获取子进程的退出状态。WIFSIGNALED(status)
: 子进程是否因信号结束。WTERMSIG(status)
: 获取导致终止的信号编号。
非阻塞调用:
waitpid(-1,&wstatus,WNOHANG); //表示非阻塞调用
非阻塞 和 阻塞
1.阻塞
会父进程处理逻辑
2.非阻塞
父进程 会去查看 子进程状态改变
但是,如果没有发生改变,父进程不阻塞,
整个程序继续往下
非阻塞 必须 套在循环中处理 //轮询
总结:
1.wait 和 waitpid都是 等待子进程状态改变
2.wait 是一种阻塞调用
3.waitpid 可以实现非阻塞调用
进程退出:
处理方式
wait //阻塞方式 --- 调用进程 一般不做额外的事情
waitpid //非阻塞的方式 --- 调用进程 逻辑一般不受影响
waitpid 想要处理到子进程
必须套在循环中
三、线程
1.线程和进程
线程:(1)轻量级的进程。(2)成为CPU执行的最小单位
进程:(1)重量级的进程。(2)成为资源分配的基本单位
线程创建和调度的时空开销都比进程小;
(1)线程存在于进程中;
(2)线程共享了进程的资源;
(3)线程结束,进程不一定结束;
2.线程的组成:线程tid,程序计数器,寄存器集合,栈;
3.线程的创建:pthread_creat
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数说明
-
pthread_t *thread
: 指向pthread_t
类型的变量的指针,用于存储新线程的tid。 -
const pthread_attr_t *attr
: 指向pthread_attr_t
结构的指针,可以用来定义线程的属性。如果传入NULL
,将使用默认属性(自己手动回收),分离属性(系统自己回收)。 -
void *(*start_routine)(void *)
: 指向将由新线程执行的函数的指针。该函数必须接受一个void*
类型的参数,并返回一个void*
。 -
void *arg
: 传递给start_routine
的参数,可以用来传递数据给新线程。
返回值
- 成功时返回
0
。 - 失败时返回一个错误码,常见的错误包括:
EAGAIN
: 系统资源不足。EINVAL
: 参数无效。EPERM
: 调用线程没有足够的权限来创建线程。
(1)编译时要联系 -lpthread.
(2)获得线程的tid tid = pthread_self();
4.线程的执行(回调函数):
5.线程的退出(在回调函数中退出)
(1)pthread_exit
参数
void *retval
: 这是将要返回给调用pthread_join
的线程的返回值。可以为NULL
(表示没有返回值)或任何其他类型的指针。
注意:在main函数中使用表示主线程结束,进程未结束,进程会在次进程都结束后,才会结束.
6.线程资源的回收:
pthread_join
-
pthread_t thread
: 要等待的线程的tid,即你想要等待的线程。 -
void **retval
: 一个指向void*
的指针的指针,用于存储线程的返回值。如果不需要返回值,可以将其设置为NULL
。