把书中提到的,shell lab中要使用的相关函数专门拿出来记录一下。
pid_t waitpid(pid_t pid, int *status, int options);
返回:如果成功,返回子进程的PID,如果WNOHANG,则为0,如果其他错误,则返回-1;
options = 0(默认情况下)时,进程吊起直到等待列表中的一个子进程终止。
如果pid > 0,那么等待集合就是一个单独的子进程,子进程进程ID为pid。
如果pid = -1,那么等待集合就是由父进程所有的子进程组成的。
修改默认情况:
设置options为常量
WNOHANG:如果等待集合中的任何子进程还没有终止就立即返回0,以便在等待子进程终止的过程中做其他工作。
WUNTRACED:返回已终止或者被停止的子进程,默认行为是只返回已终止的子进程的PID。
WNOHANG | WUNTRACED:立即返回,如果等待集合中没有任何子进程已终止或者被停止,则返回0,否则返回相应PID。
头文件:errno.h
检查已回收子线程的退出状态:
如果调用进程没有子进程,那么waitpid会返回-1,并且设置errno为ECHILD。如果waitpid函数被一个信号中断,那么它返回-1,并设置errno为EINTR。
头文件:errno.h
pid_t setpgid(pid_t pid, pid_t pgid)
将进程pid的进程组改为pgid,如果pid=0,那么这个进程就是当前进程,如果pgid=0,那么就使用pid参数为进程的id。
当进程15213是调用进程时,setpgid(0, 0)创建一个新的进程,其进程组ID是15213,并且把进程15213加入这个新的进程组中。
int kill(pid_t pid, int sig)
进程通过调用kill函数发送信号给其他进程(包括它们自己)
如果pid大于0,那么kill函数发送信号sig给进程pid,如果pid小于零,那么kill发送信号给进程组abs(pid)中的每个进程。
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal函数可以修改和信号相关的默认行为,唯一的例外是SIGSTOP和SIGKILL,它们的默认行为是不能被修改的。
1.如果handler是SIG_IGN,那么忽略类型为signum的信号
2.如果handler是SIG_DFL,那么类型为signum的信号恢复默认行为。
3.否则,handler就是用户定义的函数的地址,传入一个信号处理程序(signal handler),只要进程接受到一个类型为signum的信号,就会调用这个程序处理信号,
以此达到修改默认行为的目的。
当一个类型为k的信号被捕获,一个整型参数被设置为k,通过这个参数,信号处理程序可以处理不同的信号。
void handler(int sig) { printf("caught SIGINT\n"); exit(0); } int main() { if (signal(SIGINT, handler) == SIG_ERR) unix_error("signal error"); pause(); exit(0); }