/* polling for child exit */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
main()
{
pid_t pid1, pid2; int status;
struct rusage usage;
if ((pid1=fork())) { // fork 返回孩子的 pid 说明是 parent
printf("I am parent %d; child is %d\n",getpid(),pid1);
} else { // 返回 0 说明是 child
printf("child %d: waiting 5 seconds.\n", getpid());
sleep(5);
printf("child %d: calling cat...\n", getpid());
execl("/bin/cat", "/bin/cat", "/comp/111/news/0001.txt", NULL);
printf("we should never get here!\n");
}
printf("there's life after forking!\n");
// 先执行的是parent,创建child之后并不会马上执行,child 会先进入 ready 状态
// 直到进入下面的循环,打印一次 zzz 之后,parent 开始 sleep,此时再开始执行child
while (!(pid2 = waitpid(pid1, &status, WNOHANG))) {
// 上面的 waitpid 函数,option 参数是 WNOHANG 时,如果 status 没有改变,会返回 0
// 改变后,会返回 pid
printf("zzz...\n");
sleep (1);
}
printf("exit code for %d is %d\n", pid2, status);
} I am parent 26001; child is 26002
there's life after forking!
zzz... # 此时执行了第一次while,之后parent sleep
child 26002: waiting 5 seconds. # 执行 child,child sleep 5sec
zzz...
zzz...
zzz...
zzz...
child 26002: calling cat... # child 睡醒,继续执行
zzz... # parent 睡醒,print之后继续sleep
Welcome to COMP111. Please stay tuned here for important information.
# 之后 child结束,waitpid 返回 >0,结束 /* reaping children through SIGCHLD */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#define FALSE 0
#define TRUE 1
int done = FALSE;
// 定义一个signal handler,相当于call back 被传入的function
void reaper(int sig) {
int status;
pid_t pid2 = waitpid(-1, &status, 0);
printf("...child of %d done calling cat.\n",getpid());
printf("exit code for %d is %d\n", pid2, status);
done=TRUE; // I reaped it, so I can exit myself.
}
main() {
pid_t pid1;
// 当接收到signal:SIGCHLD时,会交由传入的handler(reaper)处理
signal(SIGCHLD,reaper);
if ((pid1=fork())) { // parent
printf("I am parent %d; child is %d\n",getpid(),pid1);
} else { // child
printf("child %d: waiting 5 seconds.\n",getpid());
sleep(5);
printf("child %d: calling cat...\n", getpid());
execl("/bin/cat", "/bin/cat", "/comp/111/news/0001.txt", NULL);
printf("we should never get here!\n");
}
printf("there's life after forking!\n");
while (!done) {
printf("doing something...\n"); sleep(1);
}
printf("got my SIGCHLD, cleaning up!\n");
// SIG_DFL 表示 default,恢复 SIGCHLD的默认处理
signal(SIGCHLD,SIG_DFL);
}I am parent 26359; child is 26360
there's life after forking!
doing something...
child 26360: waiting 5 seconds.
doing something...
doing something...
doing something...
doing something...
child 26360: calling cat...
doing something...
Welcome to COMP111. Please stay tuned here for important information.
...child of 26359 done calling cat.
exit code for 26360 is 0
got my SIGCHLD, cleaning up! #include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define SIZE 256
int main(int argc, char **argv, char **envp)
{
char command[SIZE];
int cmdlen; /* command length */
int pid; /* process identifier */
int status; /* status code for child */
while (1) {
/* get a command */
printf("by your command... ");
fgets(command,SIZE,stdin);
/* get rid of \n at end */
cmdlen = strlen(command);
if (cmdlen<256)
command[cmdlen-1]='\0';
/* now run it, as if we were a shell */
if (pid=fork()) { /* parent */
printf("child %d forked\n", pid);
// 等待 child 进程结束,执行下一行printf语句之后进行下一个循环
int newpid = waitpid(-1, &status, 0);
printf("child %d exited with status %d\n", newpid, status);
} else { /* child */
execl(command,command,NULL);
// 如果执行成功,则不会到这里
printf("command execution failed.\n");
}
}
} #define FALSE 0
#define TRUE 1
int done = FALSE;
void reaper(int sig) {
int status;
pid_t pid2 = waitpid(-1, &status, 0);
printf("exit code for child %d is %d\n", pid2, status);
done=TRUE;
}
#define SIZE 256
int main(int argc, char **argv, char **envp)
{
char command[SIZE];
int cmdlen; /* command length */
int pid; /* process identifier */
int status; /* status code for child */
signal(SIGCHLD, reaper);
while (1) {
/* get a command */
printf("by your command... ");
fgets(command,SIZE,stdin);
/* get rid of \n at end */
cmdlen = strlen(command);
if (cmdlen<256)
command[cmdlen-1]='\0';
/* now run it, as if we were a shell */
if (!(pid=fork())) { /* child */
execl(command,command,NULL);
printf("command execution failed\n");
}
}
} int main() {
for (int i = 0; i < 5; ++i) {
sleep(2);
}
printf("I'm %d, I'm gone\n", getpid());
return 0;
} vm-hw08{xguo04}75: ./a.out
by your command... ./sleep.out
by your command... ./sleep.out
by your command... ./sleep.out
by your command... ./sleep.out
by your command... ./sleep.out
by your command... ./sleep.out
by your command... I'm 4599, I'm gone
exit code for child 4599 is 0
I'm 4600, I'm gone
exit code for child 4600 is 0
I'm 4601, I'm gone
exit code for child 4601 is 0
I'm 4602, I'm gone
exit code for child 4602 is 0
I'm 4603, I'm gone
exit code for child 4603 is 0
I'm 4604, I'm gone
exit code for child 4604 is 0
^C /**************************************************
* *
* 测试,parent先退出之后,child会变为孤儿,被init收养 *
* *
**************************************************/
#include "./header.h"
int main() {
int pid = fork();
if (pid < 0) { // failed
printf("fork failed\n");
} else if (pid > 0) { // parent
printf("Im the parent of %d\n", pid);
sleep(1); // 睡一秒,保证子进程第一次输出当前parent的ID
printf("Parent terminated\n");
} else { // child
printf("Im %d, my parent is %d\n", getpid(), getppid());
sleep(5); // 保证parent已经退出
printf("After sleeping, Im %d, my parent is %d\n", getpid(), getppid());
}
return 0;
} vm-hw03{xguo04}68: ./a.out
Im the parent of 10874
Im 10874, my parent is 10872
Parent terminated
vm-hw03{xguo04}69: After sleeping, Im 10874, my parent is 1 /*******************************************************
* *
* 测试,子程序先退出,parent不做 reap,child 会变成 zombie。 *
* *
********************************************************/
#include "./header.h"
int main() {
printf("create 10 child, make them be zombies\n");
for (int i = 0; i < 10; ++i) {
if (! fork()) {
printf("Im a child, Im gonna to be a zombie\n");
exit(0);
}
}
sleep(1); // ensure children exit first
system("ps aux | grep 'Z'");
return 0;
} vm-hw04{xguo04}66: ./a.out
create 10 child, make them be zombies
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
Im a child, Im gonna to be a zombie
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
xguo04 16010 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16011 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16012 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16013 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16014 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16015 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16016 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16017 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16018 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16019 0.0 0.0 0 0 pts/6 Z+ 15:55 0:00 [a.out] <defunct>
xguo04 16020 0.0 0.0 113132 1208 pts/6 S+ 15:55 0:00 sh -c ps aux | grep 'Z'
xguo04 16022 0.0 0.0 112668 936 pts/6 S+ 15:55 0:00 grep Z /*****************************************************
如果不手动 flush stdout buffer,第一句会打印两次,因为子进
程会继承未刷新的 buffer;
当在fork之前手动 flush buffer 之后,第一句就只会打印一次了
******************************************************/
#include "./header.h"
int main(int argc, char const *argv[]) {
printf("This is gonna be printed");
// fflush(stdout); // explicitly flush stdout buffer
if (fork()) {
printf("...enventually\n");
} else {
printf("...twice\n");
}
}This is gonna be printed...enventually
This is gonna be printed...twiceThis is gonna be printed
...enventually
...twice