C语言调用execv时管道失效 execlp等exec族函数正常问题咨询
问题根本原因
你代码的问题出在execv函数的使用不符合规范,具体有两处错误:
- 第一,
execv的第二个参数要求是以NULL结尾的字符串数组,用来标记参数列表结束,你当前传入的字符串数组没有末尾的NULL哨兵,会导致execv读取参数时越界,参数解析错误。 - 第二,
execv不会自动搜索PATH环境变量查找可执行文件,第一个参数必须传入可执行文件的完整路径,你直接传"cat"、"grep"如果当前目录没有对应程序会直接执行失败。
修复方案
可以选择两种修改方式,任选其一即可:
方式1:保留execv,补全路径和末尾NULL
先确认系统中cat、grep的完整路径(通常为/bin/cat、/bin/grep,可以用which cat、which grep命令确认),然后补全参数数组的NULL:
int p_fds[2]; pipe(p_fds); int pid_left = fork(); if (pid_left == 0){ dup2(p_fds[1],STDOUT_FILENO); close(p_fds[0]); close(p_fds[1]); // 补全cat的全路径,参数数组末尾加NULL execv("/bin/cat", (char*[]){ "cat", "afile", NULL }); exit(1); } int pid_right = fork(); if (pid_right == 0){ dup2(p_fds[0], STDIN_FILENO); close(p_fds[1]); close(p_fds[0]); // 补全grep的全路径,参数数组末尾加NULL execv("/bin/grep", (char*[]){ "grep", "something", NULL }); exit(1); } close(p_fds[0]); close(p_fds[1]); waitpid(pid_left, NULL, 0); waitpid(pid_right, NULL, 0);
方式2:替换为execvp,无需写全路径
execvp和execlp逻辑一致,会自动搜索PATH找可执行文件,只需要补全参数数组末尾的NULL即可:
int p_fds[2]; pipe(p_fds); int pid_left = fork(); if (pid_left == 0){ dup2(p_fds[1],STDOUT_FILENO); close(p_fds[0]); close(p_fds[1]); // 用execvp,参数数组末尾加NULL execvp("cat", (char*[]){ "cat", "afile", NULL }); exit(1); } int pid_right = fork(); if (pid_right == 0){ dup2(p_fds[0], STDIN_FILENO); close(p_fds[1]); close(p_fds[0]); // 用execvp,参数数组末尾加NULL execvp("grep", (char*[]){ "grep", "something", NULL }); exit(1); } close(p_fds[0]); close(p_fds[1]); waitpid(pid_left, NULL, 0); waitpid(pid_right, NULL, 0);
两种修改后都可以正常实现cat afile | grep something的管道效果。
内容的提问来源于stack exchange,提问作者Ilya Zlatkin
相关产品推荐
相关产品推荐

