当在 C 中调用 execv("/bin/sh", NULL) 时,如何与子进程通信(例如 运行 通过写命令)?
how can I communicate (eg. run commands via write) with a child process when execv("/bin/sh", NULL) was called in C?
我正在尝试让我的程序能够与另一个接受输入的程序进行交互。我通过在子进程中执行 execv("/bin/sh", NULL)
来尝试使用 fork()
。现在它应该被新进程替换,/bin/sh
。现在我希望我的父进程像发送命令一样与 /bin/sh
通信。我试过使用管道,但我想我做错了什么。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if(pid == 0) { // child code
close(0); // close stdin fd
dup(pipefd[0]); // duplicate the pipe fd (will return 0)
close(pipefd[1]); // close the pipefd 1 (I dont need to write for child now)
execv("/bin/sh", NULL); // execute /bin/sh
} else { // parent code
close(1); // close stdout fd
dup(pipefd[1]); // duplicate the pipe fd (will return 1)
close(pipefd[0]); // close the pipefd 0 (I dont need to read right now)
}
write(0, "touch xxx\n", 10); // try to run a command with the parent process
waitpid(-1, WNOHANG, 0); // wait for the child to exit
}
我试图从父级写入标准输入,因为我认为 /bin/sh
从标准输入获取输入我可以写入它。可悲的是我的命令没有被执行。之后我可以输入一些东西,但它什么也没做。这是 strace 的输出:
execve("./a.out", ["./a.out"], 0x7fffffffe870 /* 41 vars */) = 0
brk(NULL) = 0x555555559000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffffffe710) = -1 EINVAL (Das Argument ist ungültig)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (Datei oder Verzeichnis nicht gefunden)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=210476, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 210476, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7f92000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]`|[=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 784, 64) = 784
pread64(3, "[=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=]GNU[=13=][=13=][=13=]0[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 80, 848) = 80
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]GNU[=13=]T647471CJ[=13=]7152"..., 68, 928) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2154488, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7f90000
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 784, 64) = 784
mmap(NULL, 1884632, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7dc3000
mmap(0x7ffff7de9000, 1359872, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7ffff7de9000
mmap(0x7ffff7f35000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x172000) = 0x7ffff7f35000
mmap(0x7ffff7f81000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7ffff7f81000
mmap(0x7ffff7f87000, 33240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7f87000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dc1000
arch_prctl(ARCH_SET_FS, 0x7ffff7f91580) = 0
mprotect(0x7ffff7f81000, 12288, PROT_READ) = 0
mprotect(0x555555557000, 4096, PROT_READ) = 0
mprotect(0x7ffff7ffb000, 8192, PROT_READ) = 0
munmap(0x7ffff7f92000, 210476) = 0
pipe([3, 4]) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ffff7f91850) = 29114
close(1) = 0
dup(4) = 1
close(3) = 0
write(0, "touch xxx\n", 10touch xxx
) = 10
wait4(-1,
希望有人能帮忙
您的 parent 进程(else
块)正在关闭并替换 fd 1
,对应于 stdout
,意思是写入它自己的 stdout
将转到 child 的 stdin
。但是你write
给parent的未修改的fd0
,stdin
.
更改代码,使 parent 写入 fd 1
、stdout
,它附加到通向 child 的 fd 0
, stdin
.
这里还有其他问题(在启用任何级别的警告的情况下进行编译会很清楚)。修正这些,这个 应该 工作(假设,正如你所说,你的系统允许 execv
接受 NULL
作为第二个参数)。
我正在尝试让我的程序能够与另一个接受输入的程序进行交互。我通过在子进程中执行 execv("/bin/sh", NULL)
来尝试使用 fork()
。现在它应该被新进程替换,/bin/sh
。现在我希望我的父进程像发送命令一样与 /bin/sh
通信。我试过使用管道,但我想我做错了什么。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if(pid == 0) { // child code
close(0); // close stdin fd
dup(pipefd[0]); // duplicate the pipe fd (will return 0)
close(pipefd[1]); // close the pipefd 1 (I dont need to write for child now)
execv("/bin/sh", NULL); // execute /bin/sh
} else { // parent code
close(1); // close stdout fd
dup(pipefd[1]); // duplicate the pipe fd (will return 1)
close(pipefd[0]); // close the pipefd 0 (I dont need to read right now)
}
write(0, "touch xxx\n", 10); // try to run a command with the parent process
waitpid(-1, WNOHANG, 0); // wait for the child to exit
}
我试图从父级写入标准输入,因为我认为 /bin/sh
从标准输入获取输入我可以写入它。可悲的是我的命令没有被执行。之后我可以输入一些东西,但它什么也没做。这是 strace 的输出:
execve("./a.out", ["./a.out"], 0x7fffffffe870 /* 41 vars */) = 0
brk(NULL) = 0x555555559000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffffffe710) = -1 EINVAL (Das Argument ist ungültig)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (Datei oder Verzeichnis nicht gefunden)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=210476, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 210476, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7f92000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]`|[=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 784, 64) = 784
pread64(3, "[=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=]GNU[=13=][=13=][=13=]0[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 80, 848) = 80
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]GNU[=13=]T647471CJ[=13=]7152"..., 68, 928) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2154488, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7f90000
pread64(3, "[=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]@[=13=][=13=][=13=][=13=][=13=][=13=][=13=]"..., 784, 64) = 784
mmap(NULL, 1884632, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7dc3000
mmap(0x7ffff7de9000, 1359872, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7ffff7de9000
mmap(0x7ffff7f35000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x172000) = 0x7ffff7f35000
mmap(0x7ffff7f81000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7ffff7f81000
mmap(0x7ffff7f87000, 33240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7f87000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dc1000
arch_prctl(ARCH_SET_FS, 0x7ffff7f91580) = 0
mprotect(0x7ffff7f81000, 12288, PROT_READ) = 0
mprotect(0x555555557000, 4096, PROT_READ) = 0
mprotect(0x7ffff7ffb000, 8192, PROT_READ) = 0
munmap(0x7ffff7f92000, 210476) = 0
pipe([3, 4]) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ffff7f91850) = 29114
close(1) = 0
dup(4) = 1
close(3) = 0
write(0, "touch xxx\n", 10touch xxx
) = 10
wait4(-1,
希望有人能帮忙
您的 parent 进程(else
块)正在关闭并替换 fd 1
,对应于 stdout
,意思是写入它自己的 stdout
将转到 child 的 stdin
。但是你write
给parent的未修改的fd0
,stdin
.
更改代码,使 parent 写入 fd 1
、stdout
,它附加到通向 child 的 fd 0
, stdin
.
这里还有其他问题(在启用任何级别的警告的情况下进行编译会很清楚)。修正这些,这个 应该 工作(假设,正如你所说,你的系统允许 execv
接受 NULL
作为第二个参数)。