对 waitpid() 使用 WCONTINUED 选项的编译器错误
Compiler error using WCONTINUED option for waitpid()
我正在做一个练习来理解信号如何在 POSIX OS 上工作,但我不知道如何编译这个例子。这是我要编译的代码:
/* file sig_ex3.c: This is a more complex example of signals
Author: Ramesh Yerraballi
Attempt to mimic:
prompt>> top | grep firefox
The parent creates a pipe and two child processes with the
write end of the pipe serving as the stdout for top and
the read end serving as the stdin for grep.
The first child that exec's top creates a new session with itself a member leader
of the process group in it. The process group's id is same as the child's pid (pid_ch1).
The second child that exec's grep joins the process group that the first child created
Now when a Ctr-c is pressed the parent relays a SIGINT to both children using
kill(-pid_ch1,SIGINT); alternative you could call killpg(pid_ch1,SIGINT);
The two child processes receive the SIGINT and their default behavior is to terminate.
Once they do that the parent reaps their exit status (using wait), prints and exits.
When a Ctrl-z is pressed the the parent relays a SIGTSTP to both children using
kill(-pid_ch1,SIGTSTP);
The parent's waitpid() call unblocks when the child receives the STOP signal. The parent
waits for 4 secs and resumes the the child that STOPped. This happens once for each of
the two children.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int pipefd[2];
int status, pid_ch1, pid_ch2, pid;
static void sig_int(int signo) {
printf("Sending signals to group:%d\n",pid_ch1); // group id is pid of first in pipeline
kill(-pid_ch1,SIGINT);
}
static void sig_tstp(int signo) {
printf("Sending SIGTSTP to group:%d\n",pid_ch1); // group id is pid of first in pipeline
kill(-pid_ch1,SIGTSTP);
}
int main(void) {
char ch[1]={0};
if (pipe(pipefd) == -1) {
perror("pipe");
exit(-1);
}
pid_ch1 = fork();
if (pid_ch1 > 0){
printf("Child1 pid = %d\n",pid_ch1);
// Parent
pid_ch2 = fork();
if (pid_ch2 > 0){
printf("Child2 pid = %d\n",pid_ch2);
if (signal(SIGINT, sig_int) == SIG_ERR)
printf("signal(SIGINT) error");
if (signal(SIGTSTP, sig_tstp) == SIG_ERR)
printf("signal(SIGTSTP) error");
close(pipefd[0]); //close the pipe in the parent
close(pipefd[1]);
int count = 0;
while (count < 2) {
// Parent's wait processing is based on the sig_ex4.c
pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);
// wait does not take options:
// waitpid(-1,&status,0) is same as wait(&status)
// with no options waitpid wait only for terminated child processes
// with options we can specify what other changes in the child's status
// we can respond to. Here we are saying we want to also know if the child
// has been stopped (WUNTRACED) or continued (WCONTINUED)
if (pid == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("child %d exited, status=%d\n", pid, WEXITSTATUS(status));count++;
} else if (WIFSIGNALED(status)) {
printf("child %d killed by signal %d\n", pid, WTERMSIG(status));count++;
} else if (WIFSTOPPED(status)) {
printf("%d stopped by signal %d\n", pid,WSTOPSIG(status));
printf("Sending CONT to %d\n", pid);
sleep(4); //sleep for 4 seconds before sending CONT
kill(pid,SIGCONT);
} else if (WIFCONTINUED(status)) {
printf("Continuing %d\n",pid);
}
}
exit(1);
} else {
//Child 2
sleep(1);
setpgid(0,pid_ch1); //child2 joins the group whose group id is same as child1's pid
close(pipefd[1]); // close the write end
dup2(pipefd[0],STDIN_FILENO);
char *myargs[3];
myargs[0] = strdup("grep"); // program: "grep" (word count)
myargs[1] = strdup("firefox"); // argument: "firefox"
myargs[2] = NULL; // marks end of array
execvp(myargs[0], myargs); // runs word count
}
} else {
// Child 1
setsid(); // child 1 creates a new session and a new group and becomes leader -
// group id is same as his pid: pid_ch1
close(pipefd[0]); // close the read end
dup2(pipefd[1],STDOUT_FILENO);
char *myargs[2];
myargs[0] = strdup("top"); // program: "top" (writes to stdout which is now pipe)
myargs[1] = NULL;
execvp(myargs[0], myargs); // runs top
}
}
这是我用来编译它的命令,以及我得到的输出:
$ gcc -D_POSIX_C_SOURCE -std=c11 -Wall sig_ex3.c -o sig_ex3
sig_ex3.c: In function ‘main’:
sig_ex3.c:66:48: error: ‘WCONTINUED’ undeclared (first use in this function); did you mean ‘WUNTRACED’?
pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);
^~~~~~~~~~
WUNTRACED
sig_ex3.c:66:48: note: each undeclared identifier is reported only once for each function it appears in
sig_ex3.c:87:20: warning: implicit declaration of function ‘WIFCONTINUED’; did you mean ‘WIFEXITED’? [-Wimplicit-function-declaration]
} else if (WIFCONTINUED(status)) {
^~~~~~~~~~~~
WIFEXITED
sig_ex3.c:99:19: warning: implicit declaration of function ‘strdup’; did you mean ‘strcmp’? [-Wimplicit-function-declaration]
myargs[0] = strdup("grep"); // program: "grep" (word count)
^~~~~~
strcmp
sig_ex3.c:99:17: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[0] = strdup("grep"); // program: "grep" (word count)
^
sig_ex3.c:100:17: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[1] = strdup("firefox"); // argument: "firefox"
^
sig_ex3.c:111:15: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[0] = strdup("top"); // program: "top" (writes to stdout which is now pipe)
^
sig_ex3.c:43:8: warning: unused variable ‘ch’ [-Wunused-variable]
char ch[1]={0};
^~
这是关于我的系统的更多信息:
$ uname -a
Linux hostname 5.0.0-38-generic #41-Ubuntu SMP Tue Dec 3 00:27:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu 8.3.0-6ubuntu1) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ldd --version
ldd (Ubuntu GLIBC 2.29-0ubuntu2) 2.29
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
我包含了 waitpid() man page 中所述的所有必要的头文件和定义。但是,我仍然收到错误 error: ‘WCONTINUED’ undeclared (first use in this function); did you mean ‘WUNTRACED’?
。我错过了什么?
感谢您的帮助。
我找出了罪魁祸首。我在使用 -std=c11
时使用了 -D_POSIX_C_SOURCE
标志。但是,我切换到 -std=gnu11
(如评论中所建议的那样解决一些警告 - 感谢@Shawn),并在使用 -std=gnu11
时删除 -D_POSIX_C_SOURCE
标志解决了错误。
我正在做一个练习来理解信号如何在 POSIX OS 上工作,但我不知道如何编译这个例子。这是我要编译的代码:
/* file sig_ex3.c: This is a more complex example of signals
Author: Ramesh Yerraballi
Attempt to mimic:
prompt>> top | grep firefox
The parent creates a pipe and two child processes with the
write end of the pipe serving as the stdout for top and
the read end serving as the stdin for grep.
The first child that exec's top creates a new session with itself a member leader
of the process group in it. The process group's id is same as the child's pid (pid_ch1).
The second child that exec's grep joins the process group that the first child created
Now when a Ctr-c is pressed the parent relays a SIGINT to both children using
kill(-pid_ch1,SIGINT); alternative you could call killpg(pid_ch1,SIGINT);
The two child processes receive the SIGINT and their default behavior is to terminate.
Once they do that the parent reaps their exit status (using wait), prints and exits.
When a Ctrl-z is pressed the the parent relays a SIGTSTP to both children using
kill(-pid_ch1,SIGTSTP);
The parent's waitpid() call unblocks when the child receives the STOP signal. The parent
waits for 4 secs and resumes the the child that STOPped. This happens once for each of
the two children.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int pipefd[2];
int status, pid_ch1, pid_ch2, pid;
static void sig_int(int signo) {
printf("Sending signals to group:%d\n",pid_ch1); // group id is pid of first in pipeline
kill(-pid_ch1,SIGINT);
}
static void sig_tstp(int signo) {
printf("Sending SIGTSTP to group:%d\n",pid_ch1); // group id is pid of first in pipeline
kill(-pid_ch1,SIGTSTP);
}
int main(void) {
char ch[1]={0};
if (pipe(pipefd) == -1) {
perror("pipe");
exit(-1);
}
pid_ch1 = fork();
if (pid_ch1 > 0){
printf("Child1 pid = %d\n",pid_ch1);
// Parent
pid_ch2 = fork();
if (pid_ch2 > 0){
printf("Child2 pid = %d\n",pid_ch2);
if (signal(SIGINT, sig_int) == SIG_ERR)
printf("signal(SIGINT) error");
if (signal(SIGTSTP, sig_tstp) == SIG_ERR)
printf("signal(SIGTSTP) error");
close(pipefd[0]); //close the pipe in the parent
close(pipefd[1]);
int count = 0;
while (count < 2) {
// Parent's wait processing is based on the sig_ex4.c
pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);
// wait does not take options:
// waitpid(-1,&status,0) is same as wait(&status)
// with no options waitpid wait only for terminated child processes
// with options we can specify what other changes in the child's status
// we can respond to. Here we are saying we want to also know if the child
// has been stopped (WUNTRACED) or continued (WCONTINUED)
if (pid == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("child %d exited, status=%d\n", pid, WEXITSTATUS(status));count++;
} else if (WIFSIGNALED(status)) {
printf("child %d killed by signal %d\n", pid, WTERMSIG(status));count++;
} else if (WIFSTOPPED(status)) {
printf("%d stopped by signal %d\n", pid,WSTOPSIG(status));
printf("Sending CONT to %d\n", pid);
sleep(4); //sleep for 4 seconds before sending CONT
kill(pid,SIGCONT);
} else if (WIFCONTINUED(status)) {
printf("Continuing %d\n",pid);
}
}
exit(1);
} else {
//Child 2
sleep(1);
setpgid(0,pid_ch1); //child2 joins the group whose group id is same as child1's pid
close(pipefd[1]); // close the write end
dup2(pipefd[0],STDIN_FILENO);
char *myargs[3];
myargs[0] = strdup("grep"); // program: "grep" (word count)
myargs[1] = strdup("firefox"); // argument: "firefox"
myargs[2] = NULL; // marks end of array
execvp(myargs[0], myargs); // runs word count
}
} else {
// Child 1
setsid(); // child 1 creates a new session and a new group and becomes leader -
// group id is same as his pid: pid_ch1
close(pipefd[0]); // close the read end
dup2(pipefd[1],STDOUT_FILENO);
char *myargs[2];
myargs[0] = strdup("top"); // program: "top" (writes to stdout which is now pipe)
myargs[1] = NULL;
execvp(myargs[0], myargs); // runs top
}
}
这是我用来编译它的命令,以及我得到的输出:
$ gcc -D_POSIX_C_SOURCE -std=c11 -Wall sig_ex3.c -o sig_ex3
sig_ex3.c: In function ‘main’:
sig_ex3.c:66:48: error: ‘WCONTINUED’ undeclared (first use in this function); did you mean ‘WUNTRACED’?
pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);
^~~~~~~~~~
WUNTRACED
sig_ex3.c:66:48: note: each undeclared identifier is reported only once for each function it appears in
sig_ex3.c:87:20: warning: implicit declaration of function ‘WIFCONTINUED’; did you mean ‘WIFEXITED’? [-Wimplicit-function-declaration]
} else if (WIFCONTINUED(status)) {
^~~~~~~~~~~~
WIFEXITED
sig_ex3.c:99:19: warning: implicit declaration of function ‘strdup’; did you mean ‘strcmp’? [-Wimplicit-function-declaration]
myargs[0] = strdup("grep"); // program: "grep" (word count)
^~~~~~
strcmp
sig_ex3.c:99:17: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[0] = strdup("grep"); // program: "grep" (word count)
^
sig_ex3.c:100:17: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[1] = strdup("firefox"); // argument: "firefox"
^
sig_ex3.c:111:15: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
myargs[0] = strdup("top"); // program: "top" (writes to stdout which is now pipe)
^
sig_ex3.c:43:8: warning: unused variable ‘ch’ [-Wunused-variable]
char ch[1]={0};
^~
这是关于我的系统的更多信息:
$ uname -a
Linux hostname 5.0.0-38-generic #41-Ubuntu SMP Tue Dec 3 00:27:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu 8.3.0-6ubuntu1) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ldd --version
ldd (Ubuntu GLIBC 2.29-0ubuntu2) 2.29
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
我包含了 waitpid() man page 中所述的所有必要的头文件和定义。但是,我仍然收到错误 error: ‘WCONTINUED’ undeclared (first use in this function); did you mean ‘WUNTRACED’?
。我错过了什么?
感谢您的帮助。
我找出了罪魁祸首。我在使用 -std=c11
时使用了 -D_POSIX_C_SOURCE
标志。但是,我切换到 -std=gnu11
(如评论中所建议的那样解决一些警告 - 感谢@Shawn),并在使用 -std=gnu11
时删除 -D_POSIX_C_SOURCE
标志解决了错误。