繁体   English   中英

如何为SIGCHLD制作信号处理程序,以便在shell中获得后台进程?

[英]How to make a signal handler for SIGCHLD that will reap background processes in shell?

目前我正在制作一个shell,它适用于它执行的前台进程。 现在我必须实现后台进程和作业控制,我真的很困惑我应该如何处理它。 我明白,如果我想在后台运行proccesses,我应该设置他们的pgid而不是等待它们,但是当我试图收获它们时我碰到了墙...

我有两个结构:工作和流程

typedef struct job {
    int is_background_job;
    pid_t pgid;
    int job_status;
    process *p;         // List of processes to execute for this job
    struct job *next;   // If a background job, it will be in a global linked list of job structs 
} job;

typedef struct process {
    char **argv;
    process *next;      // The next process to pipe to
} process;

重要的一点是,作业由一个过程结构的链接列表组成,并且有一个全局的作业结构列表,代表我正在进行的所有后台作业。

shell算法是一种标准。

贝壳:

get cmd from terminal
parse cmd and create a job struct filled with processes
if job is a background job:
  add it to global background job list
fork(), setpgid, and do the piping in a while loop of the job's processes   
if job is a foreground process:
  wait on the forked processes
else:
  don't wait // since it's a background process
continue to loop and read next cmd from terminal

现在这是我的问题。 如果我有一堆正在后台执行的进程,这意味着它们中的任何一个(来自任何一个后台作业)都可以简单地结束然后发送SIGCHLD。 令人讨厌的部分是,如果某个作业的所有进程都结束,我必须从全局作业列表中删除该作业。 我不认为我可以在我的SIGCHLD处理程序中调用waitpid(-1,&status,WNOHANG)的循环,因为在信号处理程序中,forground进程当前正在执行finsihes的可能性很小。

这是否意味着我必须在获得SIGCHLD后立即对每个作业的每个进程进行waitpid()以便我只等待非fg进程?

我真的不需要代码,只是解释一个很好的方法来做到这一点。

我知道现在这已经很晚了,可能对你来说无关紧要,但我也正在研究一个shell,并试图找出同样的问题时遇到了你的问题。

无论如何,似乎这里的问题是让主进程等待所有前台子进程,但是这很难对SIGCHLD处理程序中的waitpid进行调用。 我是如何做到这一点的,而不是在主进程中使用wait()调用,我只是在处理程序中获取所有进程并从适当的列表中删除它们(我目前有一个所有前台进程的列表和所有后台进程的列表) ,然后在主要过程中我做了:

while(foreground process list is not empty)
    pause();

pause()调用只是将进程置于睡眠状态,直到被信号唤醒为止,在这种情况下, SIGCHLD将始终唤醒进程,以便再次检查是否还有正在运行的前台进程需要等待。 希望这有助于某人!

编辑:刚刚意识到这可能会导致竞争条件,如果孩子在您检查列表不为空之后立即终止,并且在您调用pause() 简单的方法是只使用nanosleep而不是暂停,它仍然会被信号中断,但是你可以选择定期检查列表大小,这样可以避免在这种情况下的竞争条件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM