Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当在C中调用execv(";/bin/sh";,NULL)时,如何与子进程通信(例如,通过write运行命令)?_C_Fork_X86 64 - Fatal编程技术网

当在C中调用execv(";/bin/sh";,NULL)时,如何与子进程通信(例如,通过write运行命令)?

当在C中调用execv(";/bin/sh";,NULL)时,如何与子进程通信(例如,通过write运行命令)?,c,fork,x86-64,C,Fork,X86 64,我试图使我的程序能够与另一个接受输入的程序交互。我用fork()在子进程中执行execv(“/bin/sh”,NULL)尝试了这一点。现在,它应该被新流程取代,/bin/sh。现在,我希望我的父进程能够像send命令一样与/bin/sh通信。我试着用管道,但我想我做错了什么。这是我的密码: #包括 #包括 #包括 #包括 #包括 int main(){ int-pipefd[2]; 管道(pipefd); pid_t pid=fork(); 如果(pid==0){//子代码 关闭(0);//关闭

我试图使我的程序能够与另一个接受输入的程序交互。我用
fork()
在子进程中执行
execv(“/bin/sh”,NULL)
尝试了这一点。现在,它应该被新流程取代,
/bin/sh
。现在,我希望我的父进程能够像send命令一样与
/bin/sh
通信。我试着用管道,但我想我做错了什么。这是我的密码:

#包括
#包括
#包括
#包括
#包括
int main(){
int-pipefd[2];
管道(pipefd);
pid_t pid=fork();
如果(pid==0){//子代码
关闭(0);//关闭标准输入fd
dup(pipefd[0]);//复制管道fd(将返回0)
关闭(pipefd[1]);//关闭pipefd 1(我现在不需要为孩子写东西)
execv(“/bin/sh”,NULL);//执行/bin/sh
}else{//父代码
关闭(1);//关闭标准输出fd
dup(pipefd[1]);//复制管道fd(将返回1)
关闭(pipefd[0]);//关闭pipefd 0(我现在不需要阅读)
}
write(0,“touch xxx\n”,10);//尝试使用父进程运行命令
waitpid(-1,WNOHANG,0);//等待子级退出
}
我试图从父级写入stdin,因为我认为
/bin/sh
从stdin获取输入,我可以写入它。遗憾的是,我的命令没有执行。在那之后,我可以进入一些东西,但它什么也不做。以下是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, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`|\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0@\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 80, 848) = 80
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0T\246\344\4\347\334\35\347\301CJ\0\267\261\2552"..., 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, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 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,
我希望有人能提供帮助。

您的父进程(
else
块)正在关闭并替换fd
1
,对应于
stdout
,这意味着写入自己的
stdout
将转到子进程的
stdin
。但是您将
写入父级未修改的fd
0
stdin

更改代码,以便父级写入fd
1
stdout
,该stdout连接到通向子级fd
0
stdin
的管道

这里还存在其他问题(启用任何级别的警告进行编译都会说明这一点)。修复这些问题,这应该会起作用(假设您的系统允许
execv
接受
NULL
作为第二个参数)。

您的父进程(
else
块)正在关闭并替换fd
1
,对应于
stdout
,意思写入自己的
stdout
将进入子对象的
stdin
。但是您将
写入父级未修改的fd
0
stdin

更改代码,以便父级写入fd
1
stdout
,该stdout连接到通向子级fd
0
stdin
的管道


这里还存在其他问题(启用任何级别的警告进行编译都会说明这一点)。修复这些问题,这应该会起作用(假设您的系统允许
execv
接受
NULL
作为第二个参数)。

更改了它,但仍然不起作用。我将更新post
execv(“/bin/sh”,NULL)
/bin/sh
不太喜欢在argv向量设置为NULL时被调用。至少它应该有一个
argv[0]
,它是
/bin/sh
。另外,您还将
waitpid
的参数弄混了。你应该得到一个编译器警告。()哦,您没有,因为您没有包含
,所以编译器不知道
waitpid
的参数类型。但是您确实会收到一个隐式声明警告,而“隐式声明”是一个警告,您应该将其视为一个错误-在修复之前,甚至不要尝试运行代码。@BitFriends:For
execv
,或
waitpid
?在GCC上,对于后者,我肯定会得到一个编译器警告,没有任何标志(
警告:传递'waitpid'的参数2会从整数生成指针,而无需转换[-Wint conversion]
)。前者不能给出可靠的警告,因为从语言的角度来看,
NULL
是任何接受指针的函数的合法参数。当给函数一个
NULL
指针时,函数可能会爆炸,但编译器通常不知道这一点(除了偶尔的奇怪情况,编译器会执行某种程度的参数检查,例如
printf
).GCC,因为即使没有
-Wall
,它也会永远发出警告,对于您当前问题中的代码。如果您没有看到警告,请使用更好的编译器或修复您的开发环境,以避免隐藏GCC的stdout/stderr。如果没有包含标题,默认情况下,C模式下的GCC4.x或更早版本不会警告隐式声明(仅使用
-Wall
),因为这种旧的GCC默认为C89模式,而不是C99。较旧的GCC仍然使用
-std=gnu99
-std=gnu11
发出警告(带-Wall)。但实际上,您应该始终使用-Wall,并使用
strace./a.out
跟踪系统调用。更改了它,但仍然不起作用。我将更新post
execv(“/bin/sh”,NULL)
/bin/sh
不太喜欢在argv向量设置为NULL时被调用。至少它应该有一个
argv[0]
,它是
/bin/sh
。另外,您还将
waitpid
的参数弄混了。你应该得到一个编译器警告。()哦,您没有,因为您没有包含
,所以编译器不知道
waitpid
的参数类型。但是您确实会收到一个隐式声明警告,而“隐式声明”是一个警告,您应该将其视为一个错误-在修复之前,甚至不要尝试运行代码。@BitFriends:For
execv
,或
waitp