尝试实现一个shell,主要是管道。我已经编写了这个测试用例,我希望将 ls 简单地通过管道传输到 wc ...它肯定不会按预期工作。它将 ls 打印到终端,然后打印内存耗尽。
我非常不知道如何解决这个问题并让它发挥作用。 find_path 在我的所有测试中都有效。
编辑-我必须在项目中使用 execv ,它是一个类的东西,但我已经用 execvp 尝试过以防万一,它做了完全相同的事情。另外,这只是一个例子,一个测试来看看为什么它不起作用,我为两个命令和 waitpid 调用 fork 两次,因为我没有其他事情可做。
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int find_path(char* execname, char** dst)
{
char *path = getenv("PATH");
path = strdup(path);
char *pos;
path = strtok_r(path, ":", &pos);
char *originalpath = path;
do
{
char* test = (char*)calloc(strlen(path) + strlen(execname) + 2, sizeof(char));
test = strcpy(test, path);
int testlen = strlen(test);
(*(test+testlen)) = '/';
strcpy(test + testlen + 1,execname);
struct stat buf;
int result = stat(test, &buf);
if (result == 0)
{
*dst = test;
free (originalpath);
return 1;
}
else
{
free(test);
}
} while ((path = strtok_r(NULL, ":", &pos)) != NULL);
free(originalpath);
return 0;
}
int main()
{
char *cmd1 = "ls";
char *cmd2 = "wc";
int filedes[2];
pipe(filedes);
char** argv = (char**)calloc(1, sizeof(char*));
argv[0] = (char*)malloc(sizeof(char*));
argv[0] = NULL;
pid_t pid = fork();
if (pid == 0)
{
char *path;
find_path(cmd1, &path);
dup2(filedes[1],stdout);
execv(path,argv);
}
pid = fork();
if (pid == 0)
{
dup2(filedes[0], stdin);
char *path;
find_path(cmd2, &path);
execv(path, argv);
}
else
waitpid(pid);
}
通常,当程序难以调试时,最好稍微简化它以消除错误源。这是您的程序,经过简化以删除find_path
作为错误来源:
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(void)
{
int filedes[2];
pipe(filedes);
/* Run LS. */
pid_t pid = fork();
if (pid == 0) {
/* Set stdout to the input side of the pipe, and run 'ls'. */
dup2(filedes[1], 1);
char *argv[] = {"ls", NULL};
execv("/bin/ls", argv);
} else {
/* Close the input side of the pipe, to prevent it staying open. */
close(filedes[1]);
}
/* Run WC. */
pid = fork();
if (pid == 0) {
dup2(filedes[0], 0);
char *argv[] = {"wc", NULL};
execv("/usr/bin/wc", argv);
}
/* Wait for WC to finish. */
waitpid(pid);
}
这应该如您所期望的那样。
在简化过程中,出现了一些错误:
-
argv[]
未正确设置,特别是 argv[0] 被设置为 NULL;
- 该程序没有关闭正在提供给的管道的输入侧
ls
. When ls
完成后,管道没有被关闭(因为wc
进程仍然打开),防止wc
从始至终。
- 该程序混淆了值
stdout
and stdin
(其类型为FILE*
) 与文件描述符编号0
and 1
(由dup
, pipe
, etc.)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)