管道到 C 中的 grep 程序
Pipe to a grep program in C
我正在尝试将此 bash 命令:ps aux | grep bash
复制到 C 语言。我写了一些东西,但它似乎不起作用。结果字面意思是没有任何反应,在bash中再次打印提示。这是代码:
int main()
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if (pid = fork() == -1){
perror("fork error");
exit(1);
}
if (pid == 0)
{
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
exit(1);
}
else
{
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
在子进程中,如果execvp()失败,不调用exit()而是调用_ exit() 否则继承的 I/O 上下文可能会触发重复的 I/O 刷新和其他一些不希望发生的事情。
。 “==”比“=”多了一个higher precedence。这会使您的声明在这里失败:
if (pid = fork() == -1)
添加括号:
if ((pid = fork()) == -1)
这是您的程序,其中包含修正:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid == 0) {
// Child process
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(1);
} else {
// Father process
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
return 0;
}
但实际上,如果你想让它像shell那样,你应该在退出程序之前等待命令结束和return最后一个进程的退出代码在管道中。所以,父亲应该启动两个进程并等待它们结束:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
int status1, status2;
int pid1, pid2;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid1 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid1 == 0) {
// Child process#1
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(2);
} else {
// Father process
if ((pid2 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid2 == 0) {
// Child process#2
dup2(pip[1], 1);
close(pip[1]);
close(pip[0]);
execvp("ps", argexec2);
perror("exec2 failed\n");
_exit(2);
} else {
// Father process
close(pip[0]);
close(pip[1]);
// Wait for the end of the programs
if (-1 == waitpid(pid1, &status1, 0)) {
perror("wait1 error");
exit(1);
}
if (-1 == waitpid(pid2, &status2, 0)) {
perror("wait2 error");
exit(1);
}
// Return the exit code of the last program in the pipe
if (WIFEXITED(status1)) {
return WEXITSTATUS(status1);
} else {
// The process may have received a signal, return the whole status...
return status1;
}
}
}
return 0;
}
我正在尝试将此 bash 命令:ps aux | grep bash
复制到 C 语言。我写了一些东西,但它似乎不起作用。结果字面意思是没有任何反应,在bash中再次打印提示。这是代码:
int main()
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if (pid = fork() == -1){
perror("fork error");
exit(1);
}
if (pid == 0)
{
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
exit(1);
}
else
{
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
在子进程中,如果execvp()失败,不调用exit()而是调用_ exit() 否则继承的 I/O 上下文可能会触发重复的 I/O 刷新和其他一些不希望发生的事情。
。 “==”比“=”多了一个higher precedence。这会使您的声明在这里失败:
if (pid = fork() == -1)
添加括号:
if ((pid = fork()) == -1)
这是您的程序,其中包含修正:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid == 0) {
// Child process
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(1);
} else {
// Father process
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
return 0;
}
但实际上,如果你想让它像shell那样,你应该在退出程序之前等待命令结束和return最后一个进程的退出代码在管道中。所以,父亲应该启动两个进程并等待它们结束:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
int status1, status2;
int pid1, pid2;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid1 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid1 == 0) {
// Child process#1
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(2);
} else {
// Father process
if ((pid2 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid2 == 0) {
// Child process#2
dup2(pip[1], 1);
close(pip[1]);
close(pip[0]);
execvp("ps", argexec2);
perror("exec2 failed\n");
_exit(2);
} else {
// Father process
close(pip[0]);
close(pip[1]);
// Wait for the end of the programs
if (-1 == waitpid(pid1, &status1, 0)) {
perror("wait1 error");
exit(1);
}
if (-1 == waitpid(pid2, &status2, 0)) {
perror("wait2 error");
exit(1);
}
// Return the exit code of the last program in the pipe
if (WIFEXITED(status1)) {
return WEXITSTATUS(status1);
} else {
// The process may have received a signal, return the whole status...
return status1;
}
}
}
return 0;
}