为了解决我的问题,我订了
在我prctl(PR_SET_PDEATHSIG, SIGHUP);
之前调用exec*
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp)
{
int fd, pid;
pid = spawnpipe(fileName, &fd);
*fpp = fdopen(fd, "r");
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0;
clock_t launch = clock();
close(mypipe[1]);
int pidRacket = read_from_pipe(mypipe[0]);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp);
write_to_pipe(mypipe[1], pidRacket);
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
kill(pid, SIGKILL);
return 0;
}
}
,并取出我们管道PID的部分。有用!!!!!哇....
但是,stackoverflow不会让我说我已经回答了我自己的问题......
所以我试着编写一个程序,我想运行一个程序,并在cpl秒后杀死该程序,如果它没有完成。 DADDY分离了一个CHILD,它将另一个BABY分开,孩子将BABY的PID输送到DADDY,然后等待一秒钟,如果他们还没有结束他们的业务就杀死他们(这是一个令人毛骨悚然的场景)。但它不起作用,DADDY保持在S +状态,而Baby的无限循环一直持续到我ctr + c。从好的方面来说,这段代码是我在堆栈溢出时学到的所有内容的合并。我们走了。
{{1}}
归功于quinsley和vijay!
答案 0 :(得分:3)
我看代码的各种评论:
使用换行符结束消息;你现在在Linux上,而不是Windows。 Windows系统似乎鼓励人们在没有换行符的情况下留下消息,但它在Unix上尤其是Linux上无法正常工作。
如果您希望显示错误消息,请不要使用_exit()
,尤其是那些不以换行符结尾的错误消息。
不要在标准输出上报告错误消息;报告他们标准错误(这就是它的用途!)。
如果后面有一个else if (argc == 2) { }
子句,那么写else
(大括号中没有任何内容)有点奇怪,但如果没有else
子句则没有意义。您应该可以测试argc != 2
,因为这是正确的参数数量(或者更准确地说,argc == 2
之外的任何参数都会被忽略)。
如果您想睡一段涉及亚秒级时间(例如1.3秒)的时间,请使用适当的亚秒级睡眠命令之一。在这种情况下,nanosleep()
可能是要使用的功能。
除紧急情况外,请勿使用SIGKILL。用SIGKILL发出信号的过程没有机会进行清理或其他任何事情;它被立即杀死(当然,假设你的进程可以向另一个发送信号)。
case -1: printf("syserr");
之后没有break;
意味着在出错时,控制流程会进入以下case 0:
代码,而这不是必需的代码。 break;
或exit(1);
可能是合适的。 (Bullet 3也适用。)
不要关闭标准错误。代码:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
_exit(EXIT_FAILURE);
永远不会报告错误;你关闭标准错误。请记住,程序有权拥有标准错误通道。 C标准保证了它,但你必须合作并确保你没有关闭标准错误。
一些演员:
diff = ((double)((uintmax_t)(clock_t)done) - (double)((uintmax_t)(clock_t)launch)) / (double)CLOCKS_PER_SEC;
是不必要的。由于done
和launch
都属于clock_t
类型,因此不需要转换为clock_t
。对uintmax_t
的中间演员也不是必需的。你可以简单地写:
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
即便如此,三个演员阵容中的两个在理论上是多余的(三者中的任何两个都可以被删除)。
read_from_pipe()
中的代码很奇怪且容易出错。由于你有一个文件流,只需使用fscanf()
从中读取一个整数,而不是使用双算术和小数值的好奇构造,然后在末尾乘以。这是特别合适的,因为write_to_pipe()
代码使用printf("%d", ...);
来写入数据。由于c
已经是int
,因此return (int)c;
中的广告素材是多余的。
理论上,检查fdopen()
返回的流以确保操作不会失败是个好主意。
如果pipe()
函数失败,则报告标准输出上的错误,然后继续,因为没有出错。
目前尚不清楚racket
命令实际上做了什么。它在我的机器上不存在。
argv
中的spawnfp()
未使用。
pid = fork(); if (pidDos < (pid_t) 0)
会生成警告(准确地说),pidDos
可能未经初始化使用。这个条件大概应该使用pid
,而不是pidDos
。然后,您将SIGKILL信号发送到由pidDos
随机识别的PID,这不太可能带来快乐。
当我将cat
复制到racket
并调用以下代码(作为mk
构建的程序mk.c
)作为mk /etc/passwd
时,我会看到密码文件是双倍行距的(以及来自shell的关于Killed: 9
的消息。
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp)
{
int fd, pid;
pid = spawnpipe(fileName, &fd);
*fpp = fdopen(fd, "r");
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0;
clock_t launch = clock();
close(mypipe[1]);
int pidRacket = read_from_pipe(mypipe[0]);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp);
write_to_pipe(mypipe[1], pidRacket);
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
kill(pid, SIGKILL);
return 0;
}
}
我修复了本修订版中确定的一些问题,但并非所有问题。
哦,第16项:管道的读取端在第三个过程终止之前没有关闭。您需要将mypipe[1]
传递给spawnfp()
,这需要将其传递给spawnpipe()
,并且在那里创建的子项需要在执行“racket”之前关闭管道描述符。 fscanf()
在从管道读取的PID结尾处查找EOF或非数字时,会加剧这种情况。你可以在最后提供一个换行符,也可以释放父进程以在其时序循环中旋转。既然你说racket
没有终止,那就是你没有看到任何东西的原因。
再次粘贴整个程序比呈现差异更容易:
#include <assert.h>
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
assert(stream != 0);
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
assert(stream != 0);
fprintf(stderr, "%d: pidRacket = %d\n", (int)getpid(), pidRacket);
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd, int pfd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(pfd);
close(1);
//close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
fprintf(stderr, "%d: pid = %d\n", (int)getpid(), pid);
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp, int pfd)
{
int fd, pid;
pid = spawnpipe(fileName, &fd, pfd);
*fpp = fdopen(fd, "r");
assert(*fpp != 0);
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0.0;
clock_t launch = clock();
close(mypipe[1]);
fprintf(stderr, "%d: Reading from pipe:\n", (int)getpid());
int pidRacket = read_from_pipe(mypipe[0]);
fprintf(stderr, "%d: Read PID %d from pipe\n", (int)getpid(), pidRacket);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
printf("%f\n", diff);
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp, mypipe[1]);
fprintf(stderr, "%d: Writing PID %d to pipe\n", (int)getpid(), pidRacket);
write_to_pipe(mypipe[1], pidRacket);
fprintf(stderr, "%d: Written PID to pipe\n", (int)getpid());
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
fprintf(stderr, "%d: Finished reading from pipe\n", (int)getpid());
kill(pid, SIGKILL);
return 0;
}
}
答案 1 :(得分:0)
我做了一段时间以获得愚蠢的乐趣,它耗尽了大部分cpu来运行,但我确信你可以修改它以在某个时刻打破或者满足你的需求。
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, char*argv[])
{
int childpid;
int pids[100];
int count1 = 0, count2 = 0;
int count3 = 0;
L1:
childpid = fork();
if(childpid == 0)
{
}
else
{
if(childpid != 0 && childpid != -1)
{
if(count3 < 100)
{
pids[count3] = childpid;
printf("Pid:%d\n",pids[count3]);
count3++;
goto L1;
}
else
{
count3--;
goto L2;
}
}
L2:
while(count3 > 0)
{
if(pids[count3] != -1 || pids[count3] != 1)
{
printf("Killing pid:%d\n",pids[count3]);
kill(pids[count3],SIGKILL);
}
count3--;
}
if(count3 == 0)
{
goto L1;
}
}
return 0;
}