execve() 从文件重定向标准输入
execve() with redirected stdin from file
想要将标准输入重定向到 execve() 中的文件。所以程序应该像这样执行,我的意思是我在 shell 中是这样执行的并且它有效:
/opt/prog < in.txt
下面是我写的代码,但是好像不行。 in.txt 是二进制文件,我想在执行的程序中将它重定向到标准输入。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd[2];
pid_t pid;
FILE *f = fopen("in.txt", "rb");
if (pipe(fd) < 0)
return EXIT_FAILURE;
if ((pid = fork()) < 0)
return EXIT_FAILURE;
else if (pid != 0) { /* father */
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("/opt/prog", "prog", (char *)0);
printf("done\n");
} else { /* son */
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *string = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
close(fd[0]);
write(fd[1], string, 11);
}
return EXIT_SUCCESS;
}
更新 1:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd[2];
pid_t pid;
FILE *f = fopen("in.txt", "rb");
if (pipe(fd) < 0)
return EXIT_FAILURE;
if ((pid = fork()) < 0)
return EXIT_FAILURE;
else if (pid != 0) { /* father */
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *string = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
close(fd[0]);
write(fd[1], string, 11);
} else { /* son */
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("/opt/prog", "prog", (char *)0);
printf("done\n");
}
return EXIT_SUCCESS;
}
如果您只是想让进程从文件中读取,则不需要 pipe
:只需 dup2
STDIN_FILENO
上的文件描述符。你也想在 parent 中 execlp
因为否则当你的 child 时 prog
会变得意外 SIGCHLD
退出...
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
fd = open("in.txt", O_RDONLY);
if (fd < 0) {
perror("open");
return EXIT_FAILURE;
}
if ((pid = fork()) < 0) {
perror("fork");
return EXIT_FAILURE;
} else if (! pid) { /* child */
dup2(fd, STDIN_FILENO);
close(fd);
execlp("/opt/prog", "prog", (char *)0);
perror("exec");
return EXIT_FAILURE;
} else { /* parent */
close(fd);
printf("Parent waiting\n");
getchar();
}
return EXIT_SUCCESS;
}
我喜欢上面的解决方案,但是如果你只想执行 execve,并在完成后退出。你必须在父进程中使用 wait 直到子进程退出。
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd, status;
pid_t child_pid;
char c;
char *args[2] = {"/opt/prog", NULL};
if (argc != 2)
exit(1);
fd = open(argv[1], O_RDONLY);
child_pid = fork();
if (child_pid == 0) {
if (dup2(fd, STDIN_FILENO) == -1) {
perror("dup2");
return (EXIT_FAILURE);
}
close(fd);
execve(args[0], args, NULL);
}
if (child_pid != 0) {
close(fd);
wait(&status);
}
return (EXIT_SUCCESS);
}
想要将标准输入重定向到 execve() 中的文件。所以程序应该像这样执行,我的意思是我在 shell 中是这样执行的并且它有效:
/opt/prog < in.txt
下面是我写的代码,但是好像不行。 in.txt 是二进制文件,我想在执行的程序中将它重定向到标准输入。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd[2];
pid_t pid;
FILE *f = fopen("in.txt", "rb");
if (pipe(fd) < 0)
return EXIT_FAILURE;
if ((pid = fork()) < 0)
return EXIT_FAILURE;
else if (pid != 0) { /* father */
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("/opt/prog", "prog", (char *)0);
printf("done\n");
} else { /* son */
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *string = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
close(fd[0]);
write(fd[1], string, 11);
}
return EXIT_SUCCESS;
}
更新 1:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd[2];
pid_t pid;
FILE *f = fopen("in.txt", "rb");
if (pipe(fd) < 0)
return EXIT_FAILURE;
if ((pid = fork()) < 0)
return EXIT_FAILURE;
else if (pid != 0) { /* father */
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *string = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
close(fd[0]);
write(fd[1], string, 11);
} else { /* son */
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("/opt/prog", "prog", (char *)0);
printf("done\n");
}
return EXIT_SUCCESS;
}
如果您只是想让进程从文件中读取,则不需要 pipe
:只需 dup2
STDIN_FILENO
上的文件描述符。你也想在 parent 中 execlp
因为否则当你的 child 时 prog
会变得意外 SIGCHLD
退出...
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
fd = open("in.txt", O_RDONLY);
if (fd < 0) {
perror("open");
return EXIT_FAILURE;
}
if ((pid = fork()) < 0) {
perror("fork");
return EXIT_FAILURE;
} else if (! pid) { /* child */
dup2(fd, STDIN_FILENO);
close(fd);
execlp("/opt/prog", "prog", (char *)0);
perror("exec");
return EXIT_FAILURE;
} else { /* parent */
close(fd);
printf("Parent waiting\n");
getchar();
}
return EXIT_SUCCESS;
}
我喜欢上面的解决方案,但是如果你只想执行 execve,并在完成后退出。你必须在父进程中使用 wait 直到子进程退出。
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd, status;
pid_t child_pid;
char c;
char *args[2] = {"/opt/prog", NULL};
if (argc != 2)
exit(1);
fd = open(argv[1], O_RDONLY);
child_pid = fork();
if (child_pid == 0) {
if (dup2(fd, STDIN_FILENO) == -1) {
perror("dup2");
return (EXIT_FAILURE);
}
close(fd);
execve(args[0], args, NULL);
}
if (child_pid != 0) {
close(fd);
wait(&status);
}
return (EXIT_SUCCESS);
}