我正在尝试创建一个基于时间的池:您要么回答所有问题,要么时间就到。我本来的逻辑是让孩子算数,由父母问问题,但我没有实现。因此,我决定创建两个孩子,让父母安排他们的行为。
第一个孩子数时间,而第二个孩子问问题。看起来很有效,除了在程序结束时,其余的问题也被打印出来了,这有点奇怪。我的猜测是,scanf仍在等待我按下某些键,然后在控制台中充斥着垃圾。
现在,输入一些代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int askQuestions(char* array[], int size){
char* answer;
for(int i =0 ; i < size ; i ++){
printf("%s\n",array[i]);
scanf("%s",&answer);
}
return 0;
}
int count(int bound){
int index = 0;
printf("Counting started....\n");
while(index < bound){
sleep(1);
index++;
printf("%d seconds left \n", bound-index);
}
printf("Time's up!\n");
return 0;
}
int main(){
char* questions[] = {"Q1","Q2","Q3"};
int size = sizeof(questions)/sizeof(questions[0]);
int countingTime = 3;
int status;
pid_t id1,id2;
id1 = fork();
if(id1 < 0){
printf("Fork failed");
}else{
if(id1 == 0){
status = count(countingTime);
exit(status);
}else{
id2 = fork();
if(id2 == 0){
status = askQuestions(questions,size);
exit(status);
}
}
wait(0);
}
return 0;
}
输出看起来像这样:
Counting started....
Q1
2 seconds left
1 seconds left
0 seconds left
Time's up!
[modan@HP15-ManjaroCinnamon Test]$ Q2
Q3
P.S。流程肯定会停止。 (通过顶部检查) 预先感谢。
答案 0 :(得分:3)
scanf()
有两个问题:
char* answer;
...
scanf("%s",&answer);
&answer
应该读为answer
。answer
分配内存。这引起undefined behaviour,这意味着您的程序完全有权执行自己喜欢的事情。 :)
(感谢@EugeneSh.
指出缺少的与号!)
答案 1 :(得分:2)
大概您想在时间结束后杀死另一个子进程(或者,如果回答了问题,则杀死计时器);
仅在wait
被-1
中的ECHILD
返回errno
(所有个孩子都在等待)之后,才退出。
答案 2 :(得分:2)
其他文章已经指出了代码中的问题。
我只是在展示一种使用select()的替代方式,您想要做什么。
您可以这样做:
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define TIMER_IN_SECS 3
int main(void) {
char* questions[] = {"Q1","Q2","Q3"};
char answer[50] = {0};
fd_set rfds;
struct timeval tv;
int retval = 0;
int read_bytes = 0;
time_t start = 0;
time_t curr = 0;
time_t remain = 0;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_usec = 0;
start = time(NULL);
printf("You have %d seconds of time and your time start now..\n", TIMER_IN_SECS);
for (size_t i = 0; i < sizeof(questions)/sizeof(questions[0]); i++) {
curr = time(NULL);
if ((remain = (TIMER_IN_SECS - (curr - start))) <= 0) {
printf("Timeout!!! %d seconds are over\n", TIMER_IN_SECS);
break;
}
printf ("%s\n", questions[i]);
/* Wait up to remaining seconds. */
tv.tv_sec = remain;
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select()");
return -1;
}
if (retval) {
read_bytes = read(0, answer, 49);
if (read_bytes == -1) {
perror("read()");
return -1;
}
if(answer[read_bytes-1] == '\n') {
--read_bytes;
answer[read_bytes] = '\0';
}
/* In case if user just pressed enter key to skip the question */
if(read_bytes == 0) {
printf("No input..\n");
} else {
printf("Answer given by you : %s\n", answer);
}
} else {
printf("Timeout!!! %d seconds are over\n", TIMER_IN_SECS);
break;
}
}
return 0;
}
输出:
# ./mytimer
You have 3 seconds of time and your time start now..
Q1
ss
Answer given by you : ss
Q2
ff
Answer given by you : ff
Q3
e
Answer given by you : e
# ./mytimer
You have 3 seconds of time and your time start now..
Q1
tt
Answer given by you : tt
Q2
d
Answer given by you : d
Q3
Timeout!!! 3 seconds are over
# ./mytimer
You have 3 seconds of time and your time start now..
Q1
d
Answer given by you : d
Timeout!!! 3 seconds are over
答案 3 :(得分:1)
问题是您只打一次wait()
。因此,父进程仅等待一个孩子退出,而不是等待两个孩子退出,然后退出自身,另一个孩子继续运行。在您的情况下,执行倒计时的子项首先完成,因此在父进程退出后,显示问题的子项将继续运行。
同时,shell仅在等待父进程。退出时,shell将显示下一个提示。这就是为什么在提示后看到打印出来的问题的原因。
您应该循环调用wait()
:
while (wait(0) != -1) {
}
在没有可等待的子项时它将返回-1
,然后循环将结束。
您还应该解决@NPE提到的指针问题,但这不是输出奇怪的直接原因。