1 Pipelines and Process Groups
1.1 Pipeline of processes
1.the pipeline executes in parallel
sleep 10 | sleep 20 | sleep 30 | sleep 50 &
1.2 Process Grouping for Jobs
- A process group is a way to group processes into distinct jobs that are linked
- a session is way to link process groups under a single interruptive unit, like the terminal.
2 Programming with Process Groups
获得pid/pgid | 描述 |
---|---|
pid_t getpid() | get the process id for the calling process |
pid_t getppid() | get the process id of the parent of the calling proces |
pid_t getpgrp() | get the prcesso group id of the calling process |
pid_t getpgid(pid_t pid) | get the process group id for the proces identified by pid |
设置pgid | 描述 |
---|---|
pid_t setpgrp() | set the process group of the calling process to iteself, i.e. after a call to setpgr(), the following condition holds getpid() == getpgrp(). |
pid_t setpgid(pid_t pid, pid_t pgid) | set the process group id of the process identified by pid to the pgid, if pid is 0, then set the process group id of the calling process, and if pgid is 0, then the pid of the process identified by pid and is made the same as its process group, i.e., setpgid(0,0) is equivalent to calling setpgrp(). |
2.1 Retrieving the Process Group
- Each process group has a unique process group identifier, or pgid
- Upon a fork(), the child process inherits the parent’s process group.
int main(int argc, char * argv[]){
/*inherit_pgid.c*/
pid_t c_pid,pgid,pid;
c_pid = fork();
if(c_pid == 0){
/* CHILD */
pgid = getpgrp();
pid = getpid();
printf("Child: pid: %d pgid: *%d*\n", pid, pgid);
}else if (c_pid > 0){
/* PARRENT */
pgid = getpgrp();
pid = getpid();
printf("Parent: pid: %d pgid: *%d*\n", pid, pgid);
}else{
/* ERROR */
perror(argv[0]);
_exit(1);
}
return 0;
}
1.tty shell 并不是其执行进程的父进程,不具有相同的gpid
2.shell will fork each process separately in a job and assign the process group id based on the first child forked
3.这样才能通过ctrl + c
等来操作指定的进程组
/*getpgrp.c*/
int main(int argc, char * argv[]){
pid_t pid, pgid; //process id and process group for this program
pid_t ppid, ppgid; //process id and proces group for the _parent_
//current
pid = getpid();
pgid = getpgrp();
//parent
ppid = getppid();
ppgid = getpgid(ppid);
//print this parent's process pid and pgid
printf("%s: (current) pid:%d pgid:%d\n", argv[0], pid, pgid);
printf("%s: (parrent) ppid:%d pgid:%d\n", argv[0], ppid, ppgid);
return 0;
}
2.2 Setting the Process Group
方法 | 描述 |
---|
setpgrp() : sets the process group of the calling process to itself.
setpgid(pid_t pid, pid_t pgid) : set the process group of the process identified by pid to pgid.
/*setpgrp.c*/
int main(int argc, char * argv[]){
pid_t cpid, pid, pgid, cpgid; //process id's and process groups
cpid = fork();
if( cpid == 0 ){
/* CHILD */
//set process group to itself
setpgrp();
//print the pid, and pgid of child from child
pid = getpid();
pgid = getpgrp();
printf("Child: pid:%d pgid:*%d*\n", pid, pgid);
}else if( cpid > 0 ){
/* PARRENT */
//print the pid, and pgid of parent
pid = getpid();
pgid = getpgrp();
printf("Parent: pid:%d pgid: %d \n", pid, pgid);
//print the pid, and pgid of child from parent
cpgid = getpgid(cpid);
printf("Parent: Child's pid:%d pgid:*%d*\n", cpid, cpgid);
}else{
/*ERROR*/
perror("fork");
_exit(1);
}
return 0;
}
- race condition 无法判断父进程和子进程那个先执行
- you should call setpgid()=/=setpgrp() in both the parent and the child before anything depends on those values.
/*setpgid.c*/
int main(int argc, char * argv[]){
pid_t cpid, pid, pgid, cpgid; //process id's and process groups
cpid = fork();
if( cpid == 0 ){
/* CHILD */
//set process group to itself
setpgrp(); //<---------------------------!
//print the pid, and pgid of child from child
pid = getpid();
pgid = getpgrp();
printf("Child: pid:%d pgid:*%d*\n", pid, pgid);
}else if( cpid > 0 ){
/* PARRENT */
//set the proccess group of child
setpgid(cpid, cpid); //<------------------!
//print the pid, and pgid of parent
pid = getpid();
pgid = getpgrp();
printf("Parent: pid:%d pgid: %d \n", pid, pgid);
//print the pid, and pgid of child from parent
cpgid = getpgid(cpid);
printf("Parent: Child's pid:%d pgid:*%d*\n", cpid, cpgid);
}else{
/*ERROR*/
perror("fork");
_exit(1);
}
return 0;
}
3 Process Groups and Terminal Signaling
3.1 Foreground Process Group
- when we execute a pipeline, the shell will fork all the process in the job and place them in the same process group.
- Ctrl-c or Ctrl-z that the terminal will deliver special signals to the foreground job
- instead of signalling processes individually both shell and the terminal think of execution in terms of process groups.
#> sleep 10 | sleep 20 | sleep 30 | sleep 50 &
[1] 24253
#> ps
PID TTY TIME CMD
4038 pts/3 00:00:00 bash
24250 pts/3 00:00:00 sleep
24251 pts/3 00:00:00 sleep
24252 pts/3 00:00:00 sleep
24253 pts/3 00:00:00 sleep
24254 pts/3 00:00:00 ps
#> fg
sleep 10 | sleep 20 | sleep 30 | sleep 50
^C
#> ps
PID TTY TIME CMD
4038 pts/3 00:00:00 bash
24255 pts/3 00:00:00 ps
3.2 Orphaned Stopped Process Groups
参考:
https://www.usna.edu/Users/cs/aviv/classes/ic221/s16/lec/17/lec.html#coderef-bad_ref