如何在 C 中进行管道传输
How to pipe in C
所以,我想在 C 中执行以下命令行:
ps -eo user,pid,ppid 2> log.txt | grep user 2>>log.txt | sort -nk2 > out.txt
但我不确定,代码怎么可能...
我对如何将命令的输出写入文件、正确和错误输出感到困惑...
此外,我不知道应该如何构建管道以及当 pid == -1 或 pid > 0 时应该做什么...
我的代码如下:
int main(){
int fd0[2], fd1[2], pid0, pid1;
pipe(fd0);
pid0 = fork();
if (pid == 0){
close(1);
dup(fd0[0]);
fd_file= open(“./out.txt”, O_WRONLY | O_CREAT | O_TRUNC, 00600);
execl("sort","-nk2",">fd_file");
pipe(fd1);
pid1 = fork();
if (pid1 == 0){
close(1);
dup(fd1[0]);
...?
}
}
else if (pid == -1){
perror("ERROR AT SORT!\n");
exit(1);
}
return 0;
}
虽然链接两个命令看起来很简单,但尝试链接更多命令就有点棘手了。我给出了一个可以很容易地概括为链接任意数量命令的程序。我更喜欢将第一个进程保留为所有进程的父进程。
请阅读评论以获得更详细的解释。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
// Better to use define for constants
#define SUB_PROCESSES_NUMBER 2
#define FILE_OUT "out.txt"
#define FILE_LOGS "log.txt"
char *command0[] = {"ps", "-eo" "user,pid,ppid", NULL};
char *command1[] = {"grep", "^user", NULL}; // "^user" matches lines starting with "user"
char *command2[] = {"sort", "-nk2", NULL};
char **commands[SUB_PROCESSES_NUMBER + 1] = {command0, command1, command2};
int main(){
pid_t pid[SUB_PROCESSES_NUMBER]; // good practice: fork() result is pid_t, not int
int fd[SUB_PROCESSES_NUMBER][2];
// I recommend opening files now, so if you can't you won't create unecessary processes
int fd_file_out = open(FILE_OUT, O_WRONLY | O_CREAT | O_TRUNC, 00600);
if (fd_file_out < 0)
{
perror("open(" FILE_OUT ")");
return 2;
}
int fd_file_logs = open(FILE_LOGS, O_WRONLY | O_CREAT | O_TRUNC, 00600);
if (fd_file_logs < 0)
{
perror("open(" FILE_LOGS ")");
close(fd_file_out); // Not necessary, but I like to do it explicitly
return 2;
}
for (int i = 0; i < SUB_PROCESSES_NUMBER; i++) // If you decide to add more steps, this loop will be handy
{
if (pipe(fd[i]) < 0)
{
perror("pipe");
close(fd_file_out);
close(fd_file_logs);
if (i > 0)
{
close(fd[i - 1][0]);
}
return 2;
}
pid[i] = fork();
if (pid[i] < 0)
{
perror("fork()");
close(fd_file_out);
close(fd_file_logs);
if (i > 0)
{
close(fd[i - 1][0]);
}
close(fd[i][0]);
close(fd[i][1]);
return 2;
}
if (pid[i] == 0)
{
close(fd[i][0]); // First thing to do: close pipes and files you don't need any more
close(fd_file_out);
close(1);
dup(fd[i][1]);
close(fd[i][1]); // duplicated pipes are not useful any more
close(2); // Also need to redirect stderr
dup(fd_file_logs);
close(fd_file_logs);
if (i > 0)
{
close(0); // Also need to redirect stdin if this is not first process
dup(fd[i - 1][0]);
close(fd[i - 1][0]);
}
execvp(commands[i][0], commands[i]); // In a loop, we need a execv()/execvp()/execvpe() call
return 2; // Should not be reached;
}
// sub process either did execvp() or return, he won't reach this point
close(fd[i][1]);
if (i > 0)
{
close(fd[i - 1][0]);
}
}
close(fd_file_logs);
close(0);
dup(fd[SUB_PROCESSES_NUMBER - 1][0]);
close(fd[SUB_PROCESSES_NUMBER - 1][0]);
close(1);
dup(fd_file_out);
close(fd_file_out);
execvp(commands[SUB_PROCESSES_NUMBER][0], commands[SUB_PROCESSES_NUMBER]);
perror("execvp");
return 2;
}
所以,我想在 C 中执行以下命令行:
ps -eo user,pid,ppid 2> log.txt | grep user 2>>log.txt | sort -nk2 > out.txt
但我不确定,代码怎么可能... 我对如何将命令的输出写入文件、正确和错误输出感到困惑...
此外,我不知道应该如何构建管道以及当 pid == -1 或 pid > 0 时应该做什么...
我的代码如下:
int main(){
int fd0[2], fd1[2], pid0, pid1;
pipe(fd0);
pid0 = fork();
if (pid == 0){
close(1);
dup(fd0[0]);
fd_file= open(“./out.txt”, O_WRONLY | O_CREAT | O_TRUNC, 00600);
execl("sort","-nk2",">fd_file");
pipe(fd1);
pid1 = fork();
if (pid1 == 0){
close(1);
dup(fd1[0]);
...?
}
}
else if (pid == -1){
perror("ERROR AT SORT!\n");
exit(1);
}
return 0;
}
虽然链接两个命令看起来很简单,但尝试链接更多命令就有点棘手了。我给出了一个可以很容易地概括为链接任意数量命令的程序。我更喜欢将第一个进程保留为所有进程的父进程。
请阅读评论以获得更详细的解释。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
// Better to use define for constants
#define SUB_PROCESSES_NUMBER 2
#define FILE_OUT "out.txt"
#define FILE_LOGS "log.txt"
char *command0[] = {"ps", "-eo" "user,pid,ppid", NULL};
char *command1[] = {"grep", "^user", NULL}; // "^user" matches lines starting with "user"
char *command2[] = {"sort", "-nk2", NULL};
char **commands[SUB_PROCESSES_NUMBER + 1] = {command0, command1, command2};
int main(){
pid_t pid[SUB_PROCESSES_NUMBER]; // good practice: fork() result is pid_t, not int
int fd[SUB_PROCESSES_NUMBER][2];
// I recommend opening files now, so if you can't you won't create unecessary processes
int fd_file_out = open(FILE_OUT, O_WRONLY | O_CREAT | O_TRUNC, 00600);
if (fd_file_out < 0)
{
perror("open(" FILE_OUT ")");
return 2;
}
int fd_file_logs = open(FILE_LOGS, O_WRONLY | O_CREAT | O_TRUNC, 00600);
if (fd_file_logs < 0)
{
perror("open(" FILE_LOGS ")");
close(fd_file_out); // Not necessary, but I like to do it explicitly
return 2;
}
for (int i = 0; i < SUB_PROCESSES_NUMBER; i++) // If you decide to add more steps, this loop will be handy
{
if (pipe(fd[i]) < 0)
{
perror("pipe");
close(fd_file_out);
close(fd_file_logs);
if (i > 0)
{
close(fd[i - 1][0]);
}
return 2;
}
pid[i] = fork();
if (pid[i] < 0)
{
perror("fork()");
close(fd_file_out);
close(fd_file_logs);
if (i > 0)
{
close(fd[i - 1][0]);
}
close(fd[i][0]);
close(fd[i][1]);
return 2;
}
if (pid[i] == 0)
{
close(fd[i][0]); // First thing to do: close pipes and files you don't need any more
close(fd_file_out);
close(1);
dup(fd[i][1]);
close(fd[i][1]); // duplicated pipes are not useful any more
close(2); // Also need to redirect stderr
dup(fd_file_logs);
close(fd_file_logs);
if (i > 0)
{
close(0); // Also need to redirect stdin if this is not first process
dup(fd[i - 1][0]);
close(fd[i - 1][0]);
}
execvp(commands[i][0], commands[i]); // In a loop, we need a execv()/execvp()/execvpe() call
return 2; // Should not be reached;
}
// sub process either did execvp() or return, he won't reach this point
close(fd[i][1]);
if (i > 0)
{
close(fd[i - 1][0]);
}
}
close(fd_file_logs);
close(0);
dup(fd[SUB_PROCESSES_NUMBER - 1][0]);
close(fd[SUB_PROCESSES_NUMBER - 1][0]);
close(1);
dup(fd_file_out);
close(fd_file_out);
execvp(commands[SUB_PROCESSES_NUMBER][0], commands[SUB_PROCESSES_NUMBER]);
perror("execvp");
return 2;
}