- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我运行这段代码时,我的程序被终止,但我似乎不明白为什么。
int pipefd[2];
pipe(pipefd);
pid = fork();
if(pid == 0){ //child process, receives data from pipe for execution
close(0);
dup(pipefd[0]);
close(pipefd[1]);
execvp(pipeCom2[0], pipeCom2);
}
else if (pid > 1){ //parent process writes data to pipe for execution
close(1);
dup(pipefd[1]);
close(pipefd[0]);
execvp(pipeCom1[0], pipeCom1);
waitpid(pid, &status, WUNTRACED);
}
我一直在使用 cat project1.c | 进行测试grep include 命令。它正确执行并显示我的程序中的所有包含语句。
所以 pipelineCom1 包含 {"cat", "project1.c"}
并且 pipelineCom2 包含 {"grep", "include"}
在程序的前面,我使用此代码覆盖输出,并在程序结束时恢复正常。因此,当进程被终止时,输出会变得困惑。
newConfig.c_lflag &= ~(ICANON| ECHOE | ECHO);
tcsetattr(0, TCSANOW, &newConfig);
最佳答案
将评论转换为答案。
您没有关闭足够的管道文件描述符。如果将描述符复制到标准输入或输出,则应关闭两个管道描述符。
Which other pipe file descriptors should I be closing?
你有:
int pipefd[2];
pipe(pipefd);
pid = fork();
if (pid == 0) //child process, receives data from pipe for execution
{
close(0);
dup(pipefd[0]);
close(pipefd[1]);
execvp(pipeCom2[0], pipeCom2);
}
else if (pid > 1) //parent process writes data to pipe for execution
{
close(1);
dup(pipefd[1]);
close(pipefd[0]);
execvp(pipeCom1[0], pipeCom1);
waitpid(pid, &status, WUNTRACED);
}
调用 dup()
后,您需要关闭两组代码中的 pipefd[0]
和 pipefd[1]
。您也可以使用 dup2() 代替 dup() ;这通常更简单。
在这个带有试用管道的程序中,很有可能在不添加缺少的 close()
操作的情况下一切都会好起来。然而,一般来说,关闭不需要的管道描述符是至关重要的,因为打开的描述符意味着进程不会得到它期望的 EOF,或者在应该得到 SIGPIPE 信号或写入错误时不会得到,因为进程的错误管道末端仍然打开。
execvp()
此外,父进程包含一个 execvp()
调用;以下代码仅在 exec 失败时执行。当进程运行 execvp()
(或任何其他 exec*()
函数)时,仅当执行操作失败时,调用才会返回。
如果您需要重置终端,请在其中一个 exec 调用之前执行此操作,或者创建两个子级并让父级关闭其所有管道描述符并等待子级完成(死亡),然后再重置终端。考虑信号处理。在执行其他程序之前重置终端会更简单。
Earlier in the program I override output with this code and return to normal at the end of my program. So when the process is killed output is messed up.
newConfig.c_lflag &= ~(ICANON| ECHOE | ECHO);
tcsetattr(0, TCSANOW, &newConfig);
假设您有一个带有 tcgetattr()
输出的 oldConfig
,您应该这样做:
tcsetattr(0, TCSANOW, &oldConfig);
在父进程运行execvp()
之前。
你说:
pipeCom1 contains {"cat", "project1.c"}
and pipeCom2 contains {"grep", "include"}
pipeCom1
和 pipeCom2
都具有以空(指针)结尾的参数字符串列表,这对于正确操作至关重要。例如,您可以使用如下所示的硬连线参数列表:
char *pipeCom1[] = { "cat", "project1.c", 0 };
char *pipeCom2[] = { "grep", "include", 0 };
如果您愿意,可以用 NULL 代替 0。
execvp()
失败时报告错误并退出您需要考虑 execvp()
失败后会发生什么。正确的答案很少是“继续,就像没有出问题一样”(这就是您的代码所做的)。
您应该考虑向标准错误报告错误。通常,您应该以失败状态退出,使用 exit(EXIT_FAILURE);
或 _exit(EXIT_FAILURE);
或这些的一些相关项。
#include <stdio.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
struct termios oldConfig;
struct termios newConfig;
tcgetattr(0, &oldConfig); // Error check omitted
newConfig = oldConfig;
newConfig.c_lflag &= ~(ICANON| ECHOE | ECHO);
tcsetattr(0, TCSANOW, &newConfig); // Error check omitted
/* Do stuff without echoing enabled */
/* Now do some execution */
char *pipeCom1[] = { "cat", "project1.c", 0 };
char *pipeCom2[] = { "grep", "include", 0 };
int pipefd[2]; // Error check omitted
pipe(pipefd);
pid_t pid = fork();
if (pid == 0) //child process
{
close(0);
dup(pipefd[0]);
close(pipefd[1]);
close(pipefd[0]);
execvp(pipeCom2[0], pipeCom2);
perror(pipeCom2[0]);
exit(EXIT_FAILURE);
}
else if (pid > 1) //parent process
{
close(1);
dup(pipefd[1]);
close(pipefd[0]);
close(pipefd[1]);
tcsetattr(0, TCSANOW, &oldConfig);
execvp(pipeCom1[0], pipeCom1);
perror(pipeCom1[0]);
exit(EXIT_FAILURE);
}
}
假设 project1.c
是上面源代码的副本,则命令的输出为:
#include <stdio.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
char *pipeCom2[] = { "grep", "include", 0 };
进程结束后终端处于正确模式。
关于c - 使用 pipeline() 和 execvp() 杀死我的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39715220/
我是 C 语言新手,我编写了这个 C 程序,让用户输入一年中的某一天,作为返回,程序将输出月份以及该月的哪一天。该程序运行良好,但我现在想简化该程序。我知道我需要一个循环,但我不知道如何去做。这是程序
我一直在努力找出我的代码有什么问题。这个想法是创建一个小的画图程序,并有红色、绿色、蓝色和清除按钮。我有我能想到的一切让它工作,但无法弄清楚代码有什么问题。程序打开,然后立即关闭。 import ja
我想安装screen,但是接下来我应该做什么? $ brew search screen imgur-screenshot screen
我有一个在服务器端工作的 UDP 套接字应用程序。为了测试服务器端,我编写了一个简单的 python 客户端程序,它发送消息“hello world how are you”。服务器随后应接收消息,将
我有一个 shell 脚本,它运行一个 Python 程序来预处理一些数据,然后运行一个 R 程序来执行一些长时间运行的任务。我正在学习使用 Docker 并且我一直在运行 FROM r-base:l
在 Linux 中。我有一个 c 程序,它读取一个 2048 字节的文本文件作为输入。我想从 Python 脚本启动 c 程序。我希望 Python 脚本将文本字符串作为参数传递给 c 程序,而不是将
对于一个类,我被要求编写一个 VHDL 程序,该程序接受两个整数输入 A 和 B,并用 A+B 替换 A,用 A-B 替换 B。我编写了以下程序和测试平台。它完成了实现和行为语法检查,但它不会模拟。尽
module Algorithm where import System.Random import Data.Maybe import Data.List type Atom = String ty
我想找到两个以上数字的最小公倍数 求给定N个数的最小公倍数的C++程序 最佳答案 int lcm(int a, int b) { return (a/gcd(a,b))*b; } 对于gcd,请查看
这个程序有错误。谁能解决这个问题? Error is :TempRecord already defines a member called 'this' with the same paramete
当我运行下面的程序时,我在 str1 和 str2 中得到了垃圾值。所以 #include #include #include using namespace std; int main() {
这是我的作业: 一对刚出生的兔子(一公一母)被放在田里。兔子在一个月大时可以交配,因此在第二个月的月底,每对兔子都会生出两对新兔子,然后死去。 注:在第0个月,有0对兔子。第 1 个月,有 1 对兔子
我编写了一个程序,通过对字母使用 switch 命令将十进制字符串转换为十六进制,但是如果我使用 char,该程序无法正常工作!没有 switch 我无法处理 9 以上的数字。我希望你能理解我,因为我
我是 C++ 新手(虽然我有一些 C 语言经验)和 MySQL,我正在尝试制作一个从 MySQL 读取数据库的程序,我一直在关注这个 tutorial但当我尝试“构建”解决方案时出现错误。 (我正在使
仍然是一个初学者,只是尝试使用 swift 中的一些基本函数。 有人能告诉我这段代码有什么问题吗? import UIKit var guessInt: Int var randomNum = arc
我正在用 C++11 编写一个函数,它采用 constant1 + constant2 形式的表达式并将它们折叠起来。 constant1 和 constant2 存储在 std::string 中,
我用 C++ 编写了这段代码,使用运算符重载对 2 个矩阵进行加法和乘法运算。当我执行代码时,它会在第 57 行和第 59 行产生错误,非法结构操作(两行都出现相同的错误)。请解释我的错误。提前致谢:
我是 C++ 的初学者,我想编写一个简单的程序来交换字符串中的两个字符。 例如;我们输入这个字符串:“EXAMPLE”,我们给它交换这两个字符:“E”和“A”,输出应该类似于“AXEMPLA”。 我在
我需要以下代码的帮助: 声明 3 个 double 类型变量,每个代表三角形的三个边中的一个。 提示用户为第一面输入一个值,然后 将用户的输入设置为您创建的代表三角形第一条边的变量。 将最后 2 个步
我是新来的,如果问题不好请见谅 任务:将给定矩阵旋转180度 输入: 1 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 输出: 16 15 14 13 12 11
我是一名优秀的程序员,十分优秀!