c - Unix - 从子阻塞排序

标签 c linux pipe system-calls

当我发现一些我无法理解的问题时,我试图完成一个练习。 第一: 我正在尝试使用 system(string) 对文件进行排序,其中字符串包含:/usr/bin/sort -n -o %s %s。 %s 是我通过管道从父级读取的路径,并打印我看到的正确字符串。如果我删除 -o %s,一切似乎都正常。如果我添加它,程序就会卡在排序上。 这里的代码:

str=strcat(dir, str);
printf("    %s       \n", str);
sprintf(ssys, "/usr/bin/sort -n -o %s %s", str, str);
printf("     1111    \n");
system(ssys);
printf("     2222   \n");

输出是:

/home/dio/Desktop/Operating-System-PoliTo/Lab6/ex2/texts/1.txt

1111

如您所见,它没有到达第三个 printf,但就在我按 CTRL+c 终止进程时,即使文件未排序也是如此。我不明白为什么,因为如果我运行它并用 ps 检查我就会运行 sort 进程。似乎它正在等待父级完成但它没有无论如何排序。

这是完整的代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

static void sig_handler (int);

static void sig_handler (int signo)
{
        if (signo == SIGPIPE)
                exit(0);
}

int main (int argc, char **argv)
{

        signal(SIGPIPE, sig_handler);

        if (argc<3)
        {
                printf("Too little arguments");
                return 1;
        }

        int c=atoi(argv[1]);
        int *pids=malloc(sizeof(int)*c);
        int i=0, num_char_str, id, line_sort, request_pipe[c][2], data_pipe[c][2], answer_pipe[c][2];
        pid_t pid;
        char cR, cW;
        char *dir=malloc(strlen(argv[2])+1);
        char *str=malloc(strlen(argv[2])*10);
        char *ssys=malloc(strlen(argv[2])*10);
        FILE* fpp;
        FILE* fp;

        strcpy(dir, argv[2]);
        sprintf(str, "ls %s > list.txt",  dir);
        system(str);
        for(i=0; i<c; i++)
        {
                if (pipe(request_pipe[i]) == -1)
                        return 2;
                if (pipe(data_pipe[i]) == -1)
                        return 2;
                if (pipe(answer_pipe[i]) == -1)
                        return 2;
        }
        for(i=0; i<c; i++)
        {
                pid=fork();
                if(pid>0)
                        pids[i]=pid;
                if (pid == -1)
                {
                        printf("error forking");
                        return 3;
                }
                if (pid==0)
                        break;
        }
    if (pid>0) /// parent
        {
                for(i=0; i<c; i++)
                {
                        close(answer_pipe[i][1]);  /// close answer pipe on writing
                        close(request_pipe[i][1]);  /// close request pipe on writing
                        close(data_pipe[i][0]);  /// close data pipe on reading
                }
                fp=fopen("list.txt", "r");
                if (fp==NULL)
                        return 3;
                i=0;
                while (fgets(str, sizeof(str), fp)!=NULL)
                {
                        /// wait for ask
                        read(request_pipe[i][0], &cR, 1);
                        /// sending first the number of characters to read
                        /// and then the file name
                        num_char_str=(strlen(str) +1);
                        write(data_pipe[i][1], &num_char_str, sizeof(int));
                        write(data_pipe[i][1], str, num_char_str);
                        /// read the answer
                        read(answer_pipe[i][0], &id, sizeof(int));
                        //pids[i]=id;
                        read(answer_pipe[i][0], &line_sort, sizeof(int));
                        if (i==c-1)
                                i=-1;
                        i++;
                }
                /// sending termination signal to children
                for (i=0; i<c; i++)
                        kill(pids[i], SIGPIPE);
                /// producing all_sorted.txt
                strcpy(str, "touch all_sorted.txt");
                system(str);
                sprintf(str, "find %s -name \"*.txt\" -exec cat \"{}\"\";\" > all_sorted.txt", dir);
                system(str);
                /// sorting all_sorted

        }
        if (pid == 0) /// child
        {
                close(answer_pipe[i][0]);  /// close answer pipe on reading
                close(request_pipe[i][0]);  /// close request pipe on reading
                close(data_pipe[i][1]);  /// close data pipe on writing
                while (1)
                {
                        /// send request to parent
                        write(request_pipe[i][1], &cW, 1);
                        /// read length of string
                        read(data_pipe[i][0], &num_char_str, sizeof(int));
                        /// read the file name
                        read(data_pipe[i][0], str, num_char_str);
                        /// sorting
                        str=strcat(dir, str);
                        sprintf(ssys, "/usr/bin/sort -n -o %s %s", str, str);
printf("     1111    \n");
                        system(ssys);
printf("     2222   \n");
                        /// sending back data
                        id=getpid(); 
                        write(answer_pipe[i][1], &id, sizeof(int));
                        //sprintf(str, "wc -l %s/%s", dir, str);
                        //fpp=popen(str, "r");
                        //fscanf(fpp, "%d", &line_sort);
                        //pclose(fpp);
                        line_sort=1;
                        write(answer_pipe[i][1], &line_sort, sizeof(int));
                }
        }

        return 0;

}

最佳答案

谢谢,我不知道 strace。 顺便说一句,问题似乎是 fgets 读取的“\n”并给排序调用带来了一些问题

关于c - Unix - 从子阻塞排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47348200/

相关文章:

objective-c - 位掩码的递增部分

c - C 中使用指针的字符串连接

C - 读取作为命令行参数传递的文件

c - 具有自己的文件偏移量的重复文件描述符

linux - 如果脚本从另一个脚本开始,Bash 陷阱将不起作用

清晰度 -1L < 1U 和 -1L > 1UL

c++ - 根据USB VID :PID in Linux获取设备路径

c - FD_SET 从无效内存地址读取?

c - 重定向 stdin 和 stdout in child in c

我可以使用管道作为在父级读取并在子级写入吗?