大家好,
我在学校的家庭作业中完全迷失了,因为他们还没有告诉我们很多相关内容,而且我之前没有做过类似的事情。
任务是:
在C语言中创建一个程序,创建两个进程(fork函数)并通过管道(管道函数)连接它们。 第一个后代重新定向了它的' stdout进入管道并将(空格分隔的)成对的随机数写入其中(函数rand)。 延迟数字的输出(即1秒)。
第一个后代有 处理SIGUSR1信号(sigaction函数),并且在接收到这样的信号的情况下,它将字符串“TERMINATED”打印到它的stderr并终止。
第二个后代将管道输出重定向到它的stdin,将它的stdout重定向到名为out.txt的文件中 当前目录并执行一个二进制文件(execl函数)来查找最大公约数(我们以前的任务的输出,我们必须编写一个运行一个小C程序的makefile来检测一个数字是否为素数)。
父进程等待5秒,然后将SIGUSR1发送到第一个进程(数字生成器)。这应该执行两个进程的正确终止。它等待子进程终止(等待函数)并终止自身。
实际上你正在实现这样的事情:while :;回声$ RANDOM $ RANDOM;睡1;完成| ./c1_task> out.txt
我绝对迷失在此,到目前为止我一点也不幸。 我不知道从哪里开始。
有人可以告诉我什么吗?
提前致谢!
答案 0 :(得分:2)
由于我不相信让人们为他们工作,我无法为您提供解决方案。"但是,我可以向您展示完成作业时需要了解的一些概念。我也可以给你一些链接,但是如果你只是寻求你不了解的概念的帮助,你很可能会找到你需要的信息。
现在我已经提供了一段介绍性信息,我将帮助您完成解决此问题所需了解的一些概念。
我可能会填写一些遗漏的信息,如果我得到(并且觉得它值得花费)将这个变成伪教程所需的时间。 :)子>
所提供的信息可能会简化,有点含糊,或者可能会有所改进。亲爱的读者,如果您发现问题,请随时告诉我。 子>
第一个概念:fork() - ing
它是什么? fork()
通过将当前流程(大部分)复制到另一个流程,可以轻松地同时执行多项操作。 (实际上,它类似于asexual reproduction.)
例如,子进程(这是通过进行fork()
系统调用创建的新进程)继承了打开的文件描述符(这是一个重点!),它自己的父进程(拥有/拥有)等变量的副本。
示例:这是一个示例程序,用于说明一两件事。请注意wait()
。它使父进程调用fork()
,等待继续执行程序的其余部分,直到子进程终止。如果没有wait(NULL)
,我们就无法保证父亲的printf
语句会在孩子的printf
语句之后运行。
#include <stdio.h> //the usual, perror
#include <stdlib.h> //exit
#include <sys/types.h> //wait() / pid_t
#include <sys/wait.h> //wait()
#include <unistd.h> // fork()
int main () {
pid_t cpid;
//create our child.
//fork() returns -1 if the fork failed, otherwise it returns
// the pid of the child to the parent,
// and 0 to the child
cpid = fork();
//Both the child process and parent process executed the
//"cpid =" assignment.
//However, they both modified their own version of cpid.
//From now on, everything is run by both the child and parent.
//the fork failed; there is no child so we're done.
if (cpid < 0) {
perror("During attempted fork");
exit(EXIT_FAILURE);
}
//Though the if statement will be checked by both,
//cpid will equal 0 only in the child process.
if (cpid == 0) {
//This will be executed by the child.
printf("Hello. I'm your child.\n");
//Now that we've let Pops know that we're alive...
exit(EXIT_SUCCESS);
}
else if (cpid > 0) {
//wait for our child to terminate.
//I dare you to comment this out & run the program a few times.
//Does the parent ever print before the child?
wait(NULL);
printf("I proudly parented 1 child.\n");
}
return 0;
}
其他:您可以看到另一个示例here.
第二个概念:管道
什么是管道?管道是进程间通信的方法。基本上,它有一端可以放入数据(write()
是一种方法)和一端可以获取数据(使用read
)。
使用pipe()
系统调用创建管道。它出错时返回-1。它唯一的参数是两个整数数组的地址,我们称之为pipe_fds
。
如果调用成功,pipe_fds
中的第一个元素包含用于从管道读取的file descriptor
;第二个元素包含用于写入管道的file descriptor
。
您可以使用write()
写入管道,并使用read()
从管道中读取。 (有关使用管道的更多信息,请参见various places
以下是一个例子:
#include <stdio.h> //the usual, perror
#include <stdlib.h> //exit
#include <sys/types.h> //wait() / pid_t
#include <sys/wait.h> //wait()
#include <unistd.h> // fork(), pipe()
#define BUFLEN 256 //must be greater than one
int main () {
int pipe_fds[2],
pipe_ret;
pid_t cpid;
//Let's create a pipe.
//Note that we do this *before* forking so that our forked child
// has access to the pipe's file descriptors, pipe_fds.
pipe_ret = pipe(pipe_fds);
//we couldn't create our pipe
if (pipe_ret == -1) {
perror("Pipe Creation");
exit(EXIT_FAILURE);
}
//create our child.
cpid = fork();
//the fork failed; there is no child so we're done.
if (cpid < 0) {
perror("During attempted fork");
exit(EXIT_FAILURE);
}
//Am I the child?
if (cpid == 0) {
//close the childs read end of the pipe.
//Failing to close unused pipe ends is life or death!
//(Check `man 7 pipe`)
close(pipe_fds[0]);
//Send a message through the pipe.
//NOTE: For simplicity's sake, we assume that our printing works.
// In the real world, it might not write everything, etc.
//We could use `write()`, but this way is easier.
dprintf(pipe_fds[1], "Daddy, I'm alive.\n");
//We're done writing. Close write end of the pipe.
//This is the wise thing to do, but it would get closed anyways.
close(pipe_fds[1]);
//Now that we've let Pops know that we're alive...
exit(EXIT_SUCCESS);
}
else if (cpid > 0) {
char buf[BUFLEN] = {};
int bytes_read = 0;
//close *our* write end of the pipe. Important!
//Comment this out and watch your program hang.
//Again, check out `man 7 pipe`.
close(pipe_fds[1]);
//read data from pipe until we reach EOF
while ((bytes_read = read(pipe_fds[0], buf, BUFLEN - 1)) > 0) {
//null terminate our string.
//(We could use snprintf instead...)
buf[bytes_read] = '\0';
//You can comment this out to prove to yourself that
//we're the one printing the child's message.
printf("%s", buf);
}
//close read end of pipe
close(pipe_fds[0]);
//wait for our child to terminate.
wait(NULL);
printf("I proudly parented 1 child.\n");
}
return 0;
}
正如您所见,我刚刚提供了一个关于完成作业需要了解的两个概念的小教程。我需要一些睡眠,所以今晚我会把它留在那里。
阅读并试验这些示例!评论中的注释可以帮助您学习。