çUNIX管道实例 [英] C Unix Pipes Example

查看:142
本文介绍了çUNIX管道实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图执行一个空壳,主要管道。我写这个测试案例,我希望简单地管LS到厕所......绝对不能按预期工作。它输出LS到终端然后打印内存耗尽。
我在如何解决这一问题,并得到它的工作很失落。 find_path作品在我所有的测试。

编辑 - 我必须使用execv项目,它的一类的东西,但我万一有execvp尝试过了,它同样的事情。另外这只是一个例子,看到一个测试,为什么它不工作,我调用fork一次两次命令和waitpid函数因为我没有别的事情可做。

 的#include<&unistd.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / stat.h>
#包括LT&;&stdio.h中GT;
INT find_path(字符* execname,焦炭** DST)
{
        字符*路径= GETENV(PATH);
        PATH =的strdup(路径);
        字符* POS;
        PATH = strtok_r(路径:&放大器; POS)
        字符* originalpath =路径;
        做
        {
                字符*测试=(字符*)释放calloc(strlen的(路径)+ strlen的(execname)+ 2的sizeof(字符));
                测试=的strcpy(测试路径);
                INT testlen = strlen的(测试);
                (*(测试+ testlen))='/';
                的strcpy(测试+ testlen + 1,execname);
                结构统计BUF;
                INT结果= STAT(测试,和放大器; BUF);
                如果(结果== 0)
                {
                        * DST =测试;
                        免费(originalpath);
                        返回1;
                }
                其他
                {
                        自由(试验);
                }        }而((PATH = strtok_r(NULL,:&放大器; POS))!= NULL);
        免费(originalpath);
        返回0;
}诠释的main()
{
    字符* CMD1 =LS;
    字符* CMD2 =WC
    INT与filedes [2];
    管(与filedes);
    焦炭** argv的=(字符**)释放calloc(1,sizeof的(字符*));
    的argv [0] =(字符*)malloc的(sizeof的(字符*));
    的argv [0] = NULL;    将为pid_t PID =叉();
    如果(PID == 0)
    {
        字符*路径;
                find_path(CMD1,和放大器;路径);
        dup2(与filedes [1],标准输出);        execv(路径,argv的);
    }
    PID =叉();
    如果(PID == 0)
    {
        dup2(与filedes [0],标准输入);
        字符*路径;
        find_path(CMD2,和放大器;路径);
        execv(路径,argv的);    }
    其他
        waitpid函数(PID);}


解决方案

通常,当它是很难调试程序,最好是把它简化一点,以消除误差来源。这里是你的程序,简化删除 find_path 为错误的来源:

 的#include<&unistd.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / stat.h>
#包括LT&;&stdio.h中GT;INT主要(无效)
{
    INT与filedes [2];
    管(与filedes);    / *运行LS。 * /
    将为pid_t PID =叉();
    如果(PID == 0){
        / *标准输出设置到管的输入侧,并运行ls'的。 * /
        dup2(与filedes [1],1);
        的char * argv的[] = {LS,NULL};
        execv(/斌/ LS,argv的);
    }其他{
        / *关闭管道的输入端,以prevent它保持开放。 * /
        关闭(与filedes [1]);
    }    / *运行卫生间。 * /
    PID =叉();
    如果(PID == 0){
        dup2(与filedes [0],0);
        的char * argv的[] = {WC,NULL};
        execv(在/ usr /斌/ WC的argv);
    }    / *等待WC完成。 * /
    waitpid函数(PID);
}

这应该表现为您期望的那样。

在简化了一些错误就出来了:


  • 的argv [] 没有被正确设置,特别是ARGV [0]已被设置为NULL;

  • 程序未关闭,目前正在给 LS 管道的输入端。当 LS 完成后,管道没有被关闭(因为厕所进程仍然有它打开),preventing 厕所从不断整理。

  • 该计划是混淆了价值标准输出标准输入(这是类型 FILE * )与文件描述符号 0 1 (使用 DUP 管道等)

Trying to implement a shell, mainly piping. I've written this test case which I expect to simply pipe ls to wc...it definitely doesn't work as expected. It prints ls to the terminal then prints memory exhausted. I'm very lost in how to fix this and get it to work. find_path works in all of my tests.

Edit - I have to use execv for the project, its a class thing, but I've tried it with execvp just in case and it does the exact same thing. Also this is just an example, a test to see why it does not work, I call fork twice once for both commands and waitpid because I have nothing else to do.

#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);

}

解决方案

Often when it is hard to debug a program, it is best to simplify it a little to eliminate sources of error. Here is your program, simplified to remove find_path as a source of errors:

#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);
}

This should behave as you expect.

During simplification, a few errors came out:

  • argv[] wasn't being setup correctly, in particular, argv[0] was being set to NULL;
  • The program was not closing the input side of the pipe that was being given to ls. When ls finished, the pipe wasn't being closed (because the wc process still had it open), preventing wc from ever finishing.
  • The program was confusing the values stdout and stdin (which are of type FILE*) with the file descriptor numbers 0 and 1 (used by dup, pipe, etc.)

这篇关于çUNIX管道实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆