- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
好吧,简短的故事是:
我有一个需要做 X 的程序,它做了 0.25X。我使用 2 个 fork 和 4 个管道,我不知道如何调试它。 (在 linux env 中使用 eclipse c/c++)。
很长的故事:
我有一个程序需要从包含整数对的文本文件中计算 gcd(最大公约数)。这个程序有一个父亲(主)和两个 child (叉)需要通过管道与父亲交谈。 (每个 child 2 个管子。)
当我在 ubuntu 中编译并运行程序时,我没有收到任何错误,但程序没有完成其任务。我不知道它在哪里/为什么坏了。我该如何调试?我在 eclipse c/c++ 中编码,调试器无法处理 fork 。当我调试时,它从文件中读取所有数字(不计算 gcd)但是当我在 ubuntu 终端中运行时,它只读取第一行并中断。这是完整的代码:
int main(int argc, char **argv) {
if (argc != 2 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "usage: %s <FILE NAME>\n", argv[0]);
return EXIT_FAILURE;
}
int pfd_child1_r[2], pfd_child1_w[2], pfd_child2_r[2], pfd_child2_w[2];
if (pipe(pfd_child1_r) == -1 || pipe(pfd_child1_w) == -1
|| pipe(pfd_child2_r) == -1 || pipe(pfd_child2_w) == -1) {
perror("cannot pipe()");
return EXIT_FAILURE;
}
createChilds(pfd_child1_r, pfd_child1_w, pfd_child2_r, pfd_child2_w);
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("fopen(): ");
return EXIT_FAILURE;
}
char line[100];
char *token;
int numbers[2], num, line_count = 1, counter = 0, result = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
token = strtok(line, " ");
while (token != NULL) {
num = atoi(token);
if (num < 1 || counter == 2) {
fprintf(stderr, "illegal input at line %d\n",
line_count);
return EXIT_FAILURE;
}
numbers[counter] = num;
counter++;
token = strtok(NULL, " ");
}
counter = 0;
if (line_count % 2 == 0) { // use first child
write(pfd_child1_w[1], &numbers[0], sizeof(int));
write(pfd_child1_w[1], &numbers[1], sizeof(int));
} else { // use second child
write(pfd_child2_w[1], &numbers[0], sizeof(int));
write(pfd_child2_w[1], &numbers[1], sizeof(int));
}
if (line_count > 1) { // after first run alternate to get result
if (line_count % 2 == 0) { // read from second child
read(pfd_child2_r[0], &result, sizeof(int));
printf("%d %d\t\tgcd: %d\n", numbers[0], numbers[1], result);
} else { // read from first child
read(pfd_child1_r[0], &result, sizeof(int));
printf("%d %d\t\tgcd: %d\n", numbers[0], numbers[1], result);
}
}
line_count++;
}
fclose(fp);
return EXIT_SUCCESS;
}
void createChilds(int pfd_child1_r[2], int pfd_child1_w[2], int pfd_child2_r[2],
int pfd_child2_w[2]) {
switch (fork()) {
case -1:
perror("cannot fork()");
exit(EXIT_FAILURE);
case 0: /* First child: */
if (close(pfd_child1_r[0]) == -1) { /* Read end is unused */
perror("cannot close()");
exit(EXIT_FAILURE);
}
if (close(pfd_child1_w[1]) == -1) { /* Write end is unused */
perror("cannot close()");
exit(EXIT_FAILURE);
}
/* Duplicate stdout on write end of pipe; close duplicated descriptor */
if (pfd_child1_w[1] != STDOUT_FILENO) { /* Defensive check */
if (dup2(pfd_child1_r[1], STDOUT_FILENO) == -1) {
perror("cannot dup2()");
exit(EXIT_FAILURE);
}
if (close(pfd_child1_r[1]) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
}
/* Duplicate stdin on read end of pipe; close duplicated descriptor */
if (pfd_child1_w[1] != STDIN_FILENO) { /* Defensive check */
if (dup2(pfd_child1_w[0], STDIN_FILENO) == -1) {
perror("cannot dup2()");
exit(EXIT_FAILURE);
}
if (close(pfd_child1_w[0]) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
}
execlp("./v1_child", "./v1_child", NULL); /* Writes to pipe */
exit(EXIT_SUCCESS);
default: /* Parent go to next child */
break;
}
switch (fork()) {
case -1:
perror("cannot fork()");
exit(EXIT_FAILURE);
case 0: /* Second child: exec 'wc' to read from pipe */
if (close(pfd_child2_r[0]) == -1) { /* Read end is unused */
perror("cannot close()");
exit(EXIT_FAILURE);
}
if (close(pfd_child2_w[1]) == -1) { /* Write end is unused */
perror("cannot close()");
exit(EXIT_FAILURE);
}
/* Duplicate stdout on write end of pipe; close duplicated descriptor */
if (pfd_child2_w[1] != STDOUT_FILENO) { /* Defensive check */
if (dup2(pfd_child2_r[1], STDOUT_FILENO) == -1) {
perror("cannot dup2()");
exit(EXIT_FAILURE);
}
if (close(pfd_child2_r[1]) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
}
/* Duplicate stdin on read end of pipe; close duplicated descriptor */
if (pfd_child2_w[1] != STDIN_FILENO) { /* Defensive check */
if (dup2(pfd_child2_w[0], STDIN_FILENO) == -1) {
perror("cannot dup2()");
exit(EXIT_FAILURE);
}
if (close(pfd_child2_w[0]) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
}
execlp("./v1_child", "./v1_child", NULL); /* Writes to pipe */
exit(EXIT_SUCCESS);
default: /* Parent falls through */
break;
}
/* Parent closes unused file descriptors for pipe */
if (close(pfd_child1_r[1]) == -1 || close(pfd_child1_w[0]) == -1
|| close(pfd_child2_r[1]) == -1 || close(pfd_child2_w[0]) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
int gcd(int n1, int n2) {
if (n2 == 0)
return n1;
return gcd(n2, n1 % n2);
}
int main(int argc, char **argv) {
int n1, n2, result;
if (scanf("%d %d", &n1,&n2) != 2) {
fprintf(stderr, "error reading numbers in child\n");
return -1;
}
if (n1 > n2)
result = gcd(n1, n2);
else
result = gcd(n2,n1);
printf("%d", result);
}
最佳答案
如何调试
一种简单的调试方法总是添加 fprintf(stderr, "...")
对子程序的声明。然后您可以运行该程序并查看子进程在做什么。
转移值
由于您重定向 stdin 和 stdout 并在计算 gcd 的 v1_child 程序中使用 sscanf/printf,我假设您想将值作为字符串传输。
一种简单的方法是使用 fprintf 将整数写入格式化字符串。您可以使用 fdopen 将流关联到现有的管道文件描述符。
因此,您必须将数字从字符串转换为字符串。
可变长度数据和缓冲 I/O
如果您使用字符串来传输值,则每对值都有一个可变长度。通常,在 C 程序中使用换行符来表示完整的输入记录。
读/写整行的另一个原因是读/写调用也只能传输部分字节数。因此,您必须知道输入记录何时完成。另一种方法是使用二进制格式,它会自动表示具有固定长度的格式。
通过使用流处理缓冲 I/O,使用 fflush 可以确保所有缓冲数据都通过流的底层写入函数写入。
函数
可以将特征分成几个功能,使流程更容易理解。
可能的改进
这或许已经是一个开始。
另一个可能的改进可能是使用 strtol 代替 atoi,因为 atoi 不执行错误检查。类似的 sscanf 不会报告转换错误(例如行尾的非数字字符),至少我们查看分配的输入项的数量。
大概还有可能提高代码的可读性。
使用 waitpid 可以在父级中检查子级的退出状态代码。
程序
您的代码在上面提到的几点中稍作修改,然后可能如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void create_pipe(int *);
void close_fd(int);
int child(const int *, const int *);
int read_input_line(FILE *fp, char *line, int max, int *numbers, int line_count);
void write_to_child(FILE *fp, const int *numbers);
int read_from_child(FILE *fp);
int main(int argc, char *argv[]) {
if (argc != 2 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "usage: %s <FILE NAME>\n", argv[0]);
return EXIT_FAILURE;
}
int pfd_child1_r[2];
int pfd_child1_w[2];
int pfd_child2_r[2];
int pfd_child2_w[2];
create_pipe(pfd_child1_r);
create_pipe(pfd_child1_w);
create_pipe(pfd_child2_r);
create_pipe(pfd_child2_w);
pid_t pid1 = fork();
if (pid1 == 0) { //child 1
close_fd(pfd_child2_r[0]);
close_fd(pfd_child2_r[1]);
close_fd(pfd_child2_w[0]);
close_fd(pfd_child2_w[1]);
return child(pfd_child1_r, pfd_child1_w);
} else if (pid1 > 0) {
close_fd(pfd_child1_r[1]);
close_fd(pfd_child1_w[0]);
pid_t pid2 = fork();
if (pid2 == 0) { //child 2
close_fd(pfd_child1_r[0]);
close_fd(pfd_child1_w[1]);
return child(pfd_child2_r, pfd_child2_w);
} else if (pid2 > 0) {
close_fd(pfd_child2_r[1]);
close_fd(pfd_child2_w[0]);
FILE *fp_child1_w = fdopen(pfd_child1_w[1], "w");
FILE *fp_child2_w = fdopen(pfd_child2_w[1], "w");
FILE *fp_child1_r = fdopen(pfd_child1_r[0], "r");
FILE *fp_child2_r = fdopen(pfd_child2_r[0], "r");
if (!fp_child1_w || !fp_child2_w || !fp_child1_r || !fp_child2_r) {
perror("fdopen() failed");
return EXIT_FAILURE;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("fopen(): ");
return EXIT_FAILURE;
}
char line[100];
int numbers[2], line_count = 0;
while (read_input_line(fp, line, sizeof(line), numbers, line_count) == 2) {
if (line_count % 2 == 0) {
write_to_child(fp_child1_w, numbers);
} else {
write_to_child(fp_child2_w, numbers);
}
if (line_count % 2 == 0) {
int result = read_from_child(fp_child1_r);
printf("%d %d\t\tgcd: %d\n", numbers[0], numbers[1], result);
} else {
int result = read_from_child(fp_child2_r);
printf("%d %d\t\tgcd: %d\n", numbers[0], numbers[1], result);
}
line_count++;
}
//fclose closes also associated file descriptor
fclose(fp_child1_w);
fclose(fp_child2_w);
fclose(fp_child1_r);
fclose(fp_child2_r);
fclose(fp);
return EXIT_SUCCESS;
} else {
perror("second fork failed");
return EXIT_FAILURE;
}
} else {
perror("first fork failed");
return EXIT_FAILURE;
}
}
int read_input_line(FILE *fp, char *line, int max, int *numbers, int line_count) {
char *token;
int num, counter = 0;
line[0] = '\0';
if (fgets(line, max, fp) != NULL) {
token = strtok(line, " ");
while (token != NULL) {
num = atoi(token);
if (num < 1 || counter == 2) {
fprintf(stderr, "illegal input at line %d\n", line_count + 1);
exit(EXIT_FAILURE);
}
numbers[counter] = num;
counter++;
token = strtok(NULL, " ");
}
}
return counter;
}
int read_from_child(FILE *fp) {
char buf[128];
int result = -1;
if (fgets(buf, sizeof(buf), fp)) {
if (sscanf(buf, "%d", &result) == 1)
return result;
}
return -1;
}
void write_to_child(FILE *fp, const int *numbers) {
fprintf(fp, "%d %d\n", numbers[0], numbers[1]);
fflush(fp);
}
int child(const int *pfd_child_r, const int *pfd_child_w) {
dup2(pfd_child_r[1], STDOUT_FILENO);
dup2(pfd_child_w[0], STDIN_FILENO);
close_fd(pfd_child_r[0]);
close_fd(pfd_child_r[1]);
close_fd(pfd_child_w[0]);
close_fd(pfd_child_w[1]);
execlp("./v1_child", "./v1_child", NULL);
fprintf(stderr, "execution of v1_child failed\n");
exit(EXIT_FAILURE);
}
void create_pipe(int *fd) {
if (pipe(fd) == -1) {
perror("cannot pipe()");
exit(EXIT_FAILURE);
}
}
void close_fd(int fd) {
if (close(fd) == -1) {
perror("cannot close()");
exit(EXIT_FAILURE);
}
}
#include <stdio.h>
#include <stdlib.h>
int gcd(int n1, int n2) {
if (n2 == 0)
return n1;
return gcd(n2, n1 % n2);
}
int main(void) {
int n1, n2, result;
char buf[128];
while(fgets(buf, sizeof(buf), stdin)) {
if (sscanf(buf, "%d %d", &n1, &n2) != 2) {
fprintf(stderr, "error reading numbers in child\n");
return -1;
}
if (n1 > n2)
result = gcd(n1, n2);
else
result = gcd(n2, n1);
printf("%d\n", result);
fflush(stdout);
}
return EXIT_SUCCESS;
}
5 25
49 14
64 462
1155 84
5 25 gcd: 5
49 14 gcd: 7
64 462 gcd: 2
1155 84 gcd: 21
关于c - c 中的管道,2 个 fork 与 main 对话,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61193226/
我能想到的最好的标题,但要澄清的是,情况是这样的: 我正在开发一种类似短 url 的服务,该服务允许用户使用他们的 Twitter 帐户“登录”并发布内容。现在这项服务可以包含在 Tweetdeck
我正在开发一个应用程序,我需要用户使用类似聊天的系统相互交互。 为此,我想创建一个对话模型。据我所知,我将使用多对多关系。 具有以下模型:Conversation、User 和 Message,我想象
我试图在一个页面上多次实现 jquery 对话框 - 基本上,我想在用户单击某个人的名字时显示有关该人的更多信息。 我正在使用 php 生成页面。 我尝试这样做,并使其部分工作,但我只能使页面上的第一
我制作了一个 CustomTypeDialog 类,我想要的是使用不在 Activity 布局中的 EditText。当我尝试单击其中一个按钮时出现空指针异常,我认为这是因为它们不在 Activity
我有这个程序,我想知道如何继续它。我想让用户在“发生了什么”之后输入更多文本,然后让程序响应。感谢您的帮助 int main() { cout > answer; switch(an
我目前正在开发一个由 javafx ui 支持的 java 游戏。 玩家。应该可以和npc对话,这没问题。但我想要一定的文字效果。就像在 polemon 游戏或 Undertale 中一样,文本会逐个
所以基本上我正在尝试重写一个 bash 脚本,该脚本使用对话框 --radiolist 来选择区域设置、键盘、时间。目前,标签是与本地对应的数字(我为它创建了一个哈希表)。但因为我有大约 100 个语
有人可以告诉我如何使用 Watson Conversation 和其他服务(例如 Twilio)调用实时电话并进行对话吗? 我可以使用 Watson Conversation、Twilio 和 Nod
我有一个包含几个 .txt 文件的目录。让我们说 hi.txt hello.txt hello_test.txt test.txt 在 VBA 中使用文件对话框,如何过滤以在下拉列表中仅显示“*tes
我有一个 session 范围的 bean,ComponenteM,它被注入(inject)到请求范围的 bean,ComponenteC 中。 @Named @RequestScoped publi
我需要收集推文“集”,即用于我的研究的推特对话; 这些集合还需要满足以下条件 其中的推文数量,以及 参与人数。 我研究过 Twitter Streaming API、twitter-stream ge
我想在用户 Lync 客户端中打开一个新对话,其中包含预先确定的消息文本,但消息的收件人由用户选择,此过程从用户单击网站。 这可能吗? 最佳答案 这里的部分问题是,如果不知道要与谁开始对话(如果有意义
在 JBoss AS7 中工作,使用 Conversation Scope 管理浏览器选项卡中的用户交互。 我注意到我的页面附加了 ?cid 参数。这很棒 - 直到用户为页面添加书签然后尝试返回它!对
本地和远程标记以及Call-ID的组合用于识别对话。据说Call-ID是一次调用的唯一值。那么为什么 Call-ID 不单独用于识别对话呢? 最佳答案 一句话:“发夹”。 “Hairpinning”是
除了这行不通之外,这里没什么好说的,我不知道为什么。 Arduino 上的串行输出什么也没有。 C# 代码的输出变为等待响应,然后什么也没有。 当我启动 C# 程序时,Arduino 上的蓝牙卡 LE
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
目前正在开发一个应用程序,它甚至可以与 Android 2.2 一起使用,我使用支持库及其 AppCompat 主题来设计我的 UI。尽管大部分 UI 工作正常,但我有一个带有自定义布局的 Alert
我正在尝试对 MySQL 表 I 进行类似对话的输出,如下所示: Content From To Date Lorem
我已经创建了消息系统,在 messages.php 上我想显示消息对话,应该显示最后一条消息,但不知道查询,因为我是 php 新手,这里是数据库信息 table:conversation_chat
在那里,这是我的代码结构: 主要 Activity : public class PureDataActivity extends Activity { private TextView st
我是一名优秀的程序员,十分优秀!