Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.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-未使用fork()、pipe()、select()、execl()和write()到达正确的结尾_C_Multithreading_Select_Fork_Pipe - Fatal编程技术网

C-未使用fork()、pipe()、select()、execl()和write()到达正确的结尾

C-未使用fork()、pipe()、select()、execl()和write()到达正确的结尾,c,multithreading,select,fork,pipe,C,Multithreading,Select,Fork,Pipe,我使用分叉和管道来查找文件中字符串中的1和0的数量。然而,我从来没有达到我的程序的正确的目的,即计算1和0。这是一个相当小的代码量,所以这里是整个程序: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/time.h> int main (int argc, char** argv) {

我使用分叉和管道来查找文件中字符串中的1和0的数量。然而,我从来没有达到我的程序的正确的目的,即计算1和0。这是一个相当小的代码量,所以这里是整个程序:

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

int main (int argc, char** argv)
{
        int leftR, rightR;
        char *string;
        long size;
        int recursion = 0;
        if (argc == 3)
        {
                string = argv[1];
                size = strlen(string);
                printf("the string is %s\n", string);
                if (size <= 2)
                {

                        int bitCounter[2];
                        bitCounter[0] = 0;
                        bitCounter[1] = 0;
                        int i;
                        for (i=0; i < size; i++)
                        {
                                if (string[i]=='0')
                                {
                                        bitCounter[0]++;
                                }
                                else
                                {
                                        bitCounter[1]++;
                                }
                        }
                        write(STDOUT_FILENO, &bitCounter, sizeof(int)*2);
                        printf("read bits, sending back %d ones and %d zeroes\n", bitCounter[1], bitCounter[0]);
                        return 0;
                }
                else
                {
                        recursion = 1;
                }
        }
        if (argc == 2 || recursion)
        {
                char *data;
                if (!recursion)
                {
                        FILE* filePointer;
                        if ((filePointer = fopen(argv[1], "r")) == NULL)
                        {
                                perror("file didn't work");
                        }
                        fseek(filePointer, 0, SEEK_END);
                        size = ftell(filePointer);
                        fseek(filePointer, 0, SEEK_SET);
                    data = malloc(size+1);
                        fread(data, size, 1, filePointer);
                        fclose(filePointer);
                }
                else
                {
                        data = malloc(size+1);
                        data = string;
                }

                char *right;
                char *left = malloc((size/2)+1);
                if (size%2 == 0)
                {
                        right = malloc(size/2 + 1);
                }
                else
                {
                        right = malloc(size/2 + 2);
                }

                memcpy(left, data, size/2);

                if (size%2 == 0)
                {
                        memcpy(right, (size/2) + data, size/2);
                }
                else
                {
                        memcpy(right, (size/2) + data, (size/2) + 1);
                }

                int pidLeft, pidRight;
                int leftPipe[2];
                int rightPipe[2];

                pipe(leftPipe);
                pipe(rightPipe);

                fd_set readF;

                FD_ZERO(&readF);
                FD_SET(leftPipe[0], &readF);
                FD_SET(rightPipe[0], &readF);

                pidLeft = fork();
                if (pidLeft > 0)
                {
                        pidRight = fork();
                        if (pidRight > 0)
                        {
                                struct timeval timer;
                                timer.tv_sec = 3;
                                timer.tv_usec = 0;

                                close(rightPipe[1]);
                                close(leftPipe[1]);
                                dup2(leftPipe[0], STDOUT_FILENO);
                                dup2(rightPipe[0], STDOUT_FILENO);

                                select(2, &readF, NULL, NULL, &timer);
                                read(leftPipe[0], &leftR, sizeof(int)*2);
                                read(rightPipe[0], &rightR, sizeof(int)*2);
                                printf("going back to parent.\n");
                        }
                        else if (pidRight == 0)
                        {
                                close(rightPipe[0]);
                                execl("my_program", "my_program", right, "y",  NULL);
                                printf("recursion start\n");
                                exit(1);
                        }
                }
                else if (pidLeft == 0)
                {
                        close(leftPipe[0]);
                        execl("my_program", "my_program", left, "y", NULL);
                        printf("start recursion LEFT\n");
                        exit(1);
                }
                else
                {
                        fprintf(stderr, "something went wrong! No fork!\n");
                }
        }
        else
        {
                fprintf(stderr, "Please input file name properly\n");
                exit(1);
        }
    int zeroes = leftR + rightR;
    int* numOnes[2];
    numOnes[0] = &leftR + sizeof(int);
    numOnes[1] = &rightR + sizeof(int);
    int ones = (int) *numOnes[0] + (int) *numOnes[1];
    printf("0's: %d\n1's: %d\n", zeroes, ones);
    return 0;

}
有几个要点可以让您更轻松地理解代码:

  • argc在子级中执行时仅为3
  • 只有当字符串小于或等于2时,子级才会读取该字符串,否则会再次递归地将字符串切成两半(并生成更多子级)
  • 父母同时创造了一个左右两个孩子,两个孩子都承担了一半的工作
我想首先要问几个简单的问题:

  • 我是否正确使用select()和execl()
  • 我是否正确使用read()和write()
  • 我缺少的主要流程是否存在出口
  • 两个孩子是否都正确地操作和使用管道
  • (不太重要)是字符串中的奇怪字符弄乱了我的计数吗?在我的字符串中有一个空终止符吗

    • 这是一个更难破解的螺母。这段代码做的是一项晦涩难懂的工作,写得相当晦涩难懂。据我所知,它应该被称为
      my_program
      ,并且应该用一个文件名作为单个参数来调用。然后,该过程将打开文件,将其内容读入两个数组(
      left
      right
      ),而不必费心确保它们是字符串(无空终止)。然后这个过程会分叉两次。然后,使用
      (非)字符串作为参数和它是
      的信息执行自己,使用
      (非)字符串作为参数和它是右的信息执行自己。父进程没有很好的理由,在没有检查返回值的情况下,使用了
      select()
      。然后调用read来获取关于这两个管道的信息。这些读取将一直阻塞,直到数据准备就绪,因此
      select()
      实际上根本没有任何帮助。(我仍在努力找出递归位的位置。)此外,大多数系统调用都没有进行错误检查

      然而,考虑到大纲操作(读取文件、拆分、子执行和各执行一半并返回报告),我将编写如下内容:

      #include <errno.h>
      #include <stdarg.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      
      static void err_exit(char const *fmt, ...);
      
      int main(int argc, char * *argv)
      {
          int l_data[2]  = { -1, -1 };
          int r_data[2] = { -1, -1 };
          char *string;
          size_t size;
          char *arg0 = argv[0];
      
          if (argc != 2 && argc != 3)
              err_exit("Usage: %s file\n", argv[0]);
      
          if (argc == 3)
          {
              /* Child process */
              string = argv[1];
              size = strlen(string);
              fprintf(stderr, "%d: the string is %s\n", (int)getpid(), string);
              if (size <= 2)
              {
                  int bitCounter[2];
                  bitCounter[0] = 0;
                  bitCounter[1] = 0;
                  for (size_t i = 0; i < size; i++)
                  {
                      if (string[i] == '0')
                          bitCounter[0]++;
                      else if (string[i] == '1')
                          bitCounter[1]++;
                  }
                  if (write(STDOUT_FILENO, bitCounter, sizeof(int)*2) != sizeof(int)*2)
                      err_exit("%d: failed to write on standard output\n",
                              (int)getpid());
                  fprintf(stderr, "%d: read bits, sending back %d ones and %d zeroes\n",
                         (int)getpid(), bitCounter[1], bitCounter[0]);
                  exit(0);
              }
              fprintf(stderr, "%d: doing recursion - string too big (%zu)\n",
                      (int)getpid(), size);
          }
      
          char *data = string;
          if (argc == 2)
          {
              FILE *filePointer;
              if ((filePointer = fopen(argv[1], "r")) == NULL)
              {
                  perror("file didn't work");
                  exit(1);
              }
              fseek(filePointer, 0, SEEK_END);
              size = ftell(filePointer);
              fseek(filePointer, 0, SEEK_SET);
              data = malloc(size+1);
              fread(data, size, 1, filePointer);
              data[size] = '\0';
              if (data[size-1] == '\n')
                  data[--size] = '\0';
              fclose(filePointer);
              fprintf(stderr, "%d: data <<%s>>\n", (int)getpid(), data);
          }
      
          size_t l_size = size/2;
          size_t r_size = size - l_size;
          char *left = malloc(l_size+1);
          char *right = malloc(r_size+1);
      
          memcpy(left, data, l_size);
          left[l_size] = '\0';
          memcpy(right, data + l_size, r_size);
          right[r_size] = '\0';
      
          int l_pid, r_pid;
          int l_pipe[2] = { -1, -1 };
          int r_pipe[2] = { -1, -1 };
      
          if (pipe(l_pipe) != 0 || pipe(r_pipe) != 0)
              err_exit("%d: Failed to create pipes\n", (int)getpid());
      
          fprintf(stderr, "%d: forking (l_size = %zu, r_size = %zu)\n",
                  (int)getpid(), l_size, r_size);
          l_pid = fork();
          if (l_pid < 0)
              err_exit("%d: Failed to fork() left child\n", (int)getpid());
          else if (l_pid == 0)
          {
              dup2(l_pipe[1], STDOUT_FILENO);
              close(l_pipe[0]);
              close(l_pipe[1]);
              close(r_pipe[0]);
              close(r_pipe[1]);
              fprintf(stderr, "%d: left execing with string <<%s>>\n", (int)getpid(), left);
              execl(arg0, arg0, left, "y", NULL);
              err_exit("%d: failed to start recursion LEFT\n", (int)getpid());
          }
          else if ((r_pid = fork()) < 0)
              err_exit("%d: Failed to fork() right child\n", (int)getpid());
          else if (r_pid == 0)
          {
              dup2(r_pipe[1], STDOUT_FILENO);
              close(l_pipe[0]);
              close(l_pipe[1]);
              close(r_pipe[0]);
              close(r_pipe[1]);
              fprintf(stderr, "%d: right execing with string <<%s>>\n", (int)getpid(), right);
              execl(arg0, arg0, right, "y",  NULL);
              err_exit("%d: failed to start recursion RIGHT\n", (int)getpid());
          }
          else
          {
              /* Parent process */
              int nbytes;
              close(r_pipe[1]);
              close(l_pipe[1]);
              if ((nbytes = read(l_pipe[0], l_data, sizeof(int)*2)) != sizeof(int)*2)
                  err_exit("%d: Read left pipe failed (%d)\n", (int)getpid(), nbytes);
              if ((nbytes = read(r_pipe[0], r_data, sizeof(int)*2)) != sizeof(int)*2)
                  err_exit("%d: Read right pipe failed (%d)\n", (int)getpid(), nbytes);
              close(l_pipe[0]);
              close(r_pipe[0]);
          }
      
          int zeroes = l_data[0] + r_data[0];
          int ones   = l_data[1] + r_data[1];
          if (argc == 3)
          {
              int data[2] = { zeroes, ones };
              if (write(STDOUT_FILENO, data, sizeof(data)) != sizeof(data))
                  err_exit("%d: failed to read binary data from stdin\n", (int)getpid());
              fprintf(stderr, "%d: binary write to stdout OK\n", (int)getpid());
          }
      
          fprintf(stderr, "%d: 0's = %d, 1's = %d\n", (int)getpid(), zeroes, ones);
          return 0;
      }
      
      static void err_exit(char const *fmt, ...)
      {
          int errnum = errno;
          va_list args;
          va_start(args, fmt);
          vfprintf(stderr, fmt, args);
          va_end(args);
          if (errnum != 0)
              fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
          exit(1);
      }
      
      输出为:

      11070: data <<0101010111111>>
      11070: forking (l_size = 6, r_size = 7)
      11073: right execing with string <<0111111>>
      11072: left execing with string <<010101>>
      11072: the string is 010101
      11072: doing recursion - string too big (6)
      11072: forking (l_size = 3, r_size = 3)
      11073: the string is 0111111
      11073: doing recursion - string too big (7)
      11073: forking (l_size = 3, r_size = 4)
      11074: left execing with string <<010>>
      11075: right execing with string <<101>>
      11076: left execing with string <<011>>
      11077: right execing with string <<1111>>
      11074: the string is 010
      11074: doing recursion - string too big (3)
      11074: forking (l_size = 1, r_size = 2)
      11078: left execing with string <<0>>
      11076: the string is 011
      11076: doing recursion - string too big (3)
      11076: forking (l_size = 1, r_size = 2)
      11079: right execing with string <<10>>
      11075: the string is 101
      11075: doing recursion - string too big (3)
      11075: forking (l_size = 1, r_size = 2)
      11080: left execing with string <<0>>
      11077: the string is 1111
      11077: doing recursion - string too big (4)
      11077: forking (l_size = 2, r_size = 2)
      11082: right execing with string <<11>>
      11081: left execing with string <<1>>
      11083: right execing with string <<01>>
      11084: left execing with string <<11>>
      11085: right execing with string <<11>>
      11079: the string is 10
      11078: the string is 0
      11079: read bits, sending back 1 ones and 1 zeroes
      11078: read bits, sending back 0 ones and 1 zeroes
      11074: binary write to stdout OK
      11074: 0's = 2, 1's = 1
      11082: the string is 11
      11082: read bits, sending back 2 ones and 0 zeroes
      11080: the string is 0
      11080: read bits, sending back 0 ones and 1 zeroes
      11076: binary write to stdout OK
      11076: 0's = 1, 1's = 2
      11081: the string is 1
      11081: read bits, sending back 1 ones and 0 zeroes
      11084: the string is 11
      11084: read bits, sending back 2 ones and 0 zeroes
      11083: the string is 01
      11083: read bits, sending back 1 ones and 1 zeroes
      11075: binary write to stdout OK
      11075: 0's = 1, 1's = 2
      11072: binary write to stdout OK
      11072: 0's = 3, 1's = 3
      11085: the string is 11
      11085: read bits, sending back 2 ones and 0 zeroes
      11077: binary write to stdout OK
      11077: 0's = 0, 1's = 4
      11073: binary write to stdout OK
      11073: 0's = 1, 1's = 6
      11070: 0's = 4, 1's = 9
      
      11070:数据
      11070:分叉(l_尺寸=6,r_尺寸=7)
      11073:使用字符串右执行
      11072:使用字符串左执行
      11072:字符串是010101
      11072:执行递归-字符串太大(6)
      11072:分叉(l_尺寸=3,r_尺寸=3)
      11073:字符串是011111
      11073:执行递归-字符串太大(7)
      11073:分叉(l_尺寸=3,r_尺寸=4)
      11074:使用字符串左执行
      11075:使用字符串右执行
      11076:使用字符串左执行
      11077:使用字符串右执行
      11074:字符串是010
      11074:执行递归-字符串太大(3)
      11074:分叉(l_尺寸=1,r_尺寸=2)
      11078:使用字符串左执行
      11076:字符串是011
      11076:执行递归-字符串太大(3)
      11076:分叉(l_尺寸=1,r_尺寸=2)
      11079:使用字符串右执行
      11075:字符串是101
      11075:执行递归-字符串太大(3)
      11075:分叉(l_尺寸=1,r_尺寸=2)
      11080:使用字符串左执行
      11077:字符串是1111
      11077:执行递归-字符串太大(4)
      11077:分叉(l_尺寸=2,r_尺寸=2)
      11082:使用字符串右执行
      11081:使用字符串左执行
      11083:使用字符串右执行
      11084:使用字符串左执行
      11085:使用字符串右执行
      11079:字符串是10
      11078:字符串是0
      11079:读取位,返回1个1和1个0
      11078:读取位,发送回0个1和1个0
      11074:二进制写入标准输出正常
      11074:0=2,1=1
      11082:字符串是11
      11082:读取位,发送回2个1和0个0
      11080:字符串为0
      11080:读取位,发送回0个1和1个0
      11076:对标准输出的二进制写入正常
      11076:0=1,1=2
      11081:字符串是1
      11081:读取位,发送回1个1和0个0
      11084:字符串是11
      11084:读取位,返回2个1和0个0
      11083:字符串是01
      11083:读取位,发送回1个1和1个0
      11075:二进制写入标准输出正常
      11075:0=1,1=2
      11072:二进制写入标准输出正常
      11072:0=3,1=3
      11085:字符串是11
      11085:读取位,返回2个1和0个0
      11077:二进制写入标准输出正常
      11077:0=0,1=4
      11073:二进制写入标准输出正常
      11073:0=1,1=6
      11070:0=4,1=9
      
      请发布编译无错误的代码:
      int zeroes=*leftR+*righter生成错误,因为
      leftR
      righter
      都不是指针。下一行也有类似的抱怨。修正了,很抱歉。我可能不会用“修正”这个词。此代码:
      intrights=(int)&rightR;int lefts=(int)&leftR;整数零=左+右;int one=(int)(&leftR+sizeof(int))+(int)(&rightR+sizeof(int))异常-而且极不可能是正确的。将两个地址相加会产生垃圾,而不是答案。我不确定你认为
      (&leftR+sizeof(int))
      会产生什么,但这不是“定义的行为”。此外,鉴于
      leftR
      rightR
      都是单个整数,代码
      读取(leftPipe[0],&leftR,sizeof(int)*2);读取(右管道[0],&右管道,尺寸(整数)*2)
      将两个
      int
      值读入每个单个整数中保证是未定义的行为。是的,这是最肯定的情况。主要的问题是我的程序甚至没有到达最后一个区域,我甚至无法正确地调试它。本质上,
      (&leftR+sizeof(int))
      应该从从从左子级传递的数组
      位计数器中取出下一个元素。不管怎样,我对一个
      
      0101010111111
      
      11070: data <<0101010111111>>
      11070: forking (l_size = 6, r_size = 7)
      11073: right execing with string <<0111111>>
      11072: left execing with string <<010101>>
      11072: the string is 010101
      11072: doing recursion - string too big (6)
      11072: forking (l_size = 3, r_size = 3)
      11073: the string is 0111111
      11073: doing recursion - string too big (7)
      11073: forking (l_size = 3, r_size = 4)
      11074: left execing with string <<010>>
      11075: right execing with string <<101>>
      11076: left execing with string <<011>>
      11077: right execing with string <<1111>>
      11074: the string is 010
      11074: doing recursion - string too big (3)
      11074: forking (l_size = 1, r_size = 2)
      11078: left execing with string <<0>>
      11076: the string is 011
      11076: doing recursion - string too big (3)
      11076: forking (l_size = 1, r_size = 2)
      11079: right execing with string <<10>>
      11075: the string is 101
      11075: doing recursion - string too big (3)
      11075: forking (l_size = 1, r_size = 2)
      11080: left execing with string <<0>>
      11077: the string is 1111
      11077: doing recursion - string too big (4)
      11077: forking (l_size = 2, r_size = 2)
      11082: right execing with string <<11>>
      11081: left execing with string <<1>>
      11083: right execing with string <<01>>
      11084: left execing with string <<11>>
      11085: right execing with string <<11>>
      11079: the string is 10
      11078: the string is 0
      11079: read bits, sending back 1 ones and 1 zeroes
      11078: read bits, sending back 0 ones and 1 zeroes
      11074: binary write to stdout OK
      11074: 0's = 2, 1's = 1
      11082: the string is 11
      11082: read bits, sending back 2 ones and 0 zeroes
      11080: the string is 0
      11080: read bits, sending back 0 ones and 1 zeroes
      11076: binary write to stdout OK
      11076: 0's = 1, 1's = 2
      11081: the string is 1
      11081: read bits, sending back 1 ones and 0 zeroes
      11084: the string is 11
      11084: read bits, sending back 2 ones and 0 zeroes
      11083: the string is 01
      11083: read bits, sending back 1 ones and 1 zeroes
      11075: binary write to stdout OK
      11075: 0's = 1, 1's = 2
      11072: binary write to stdout OK
      11072: 0's = 3, 1's = 3
      11085: the string is 11
      11085: read bits, sending back 2 ones and 0 zeroes
      11077: binary write to stdout OK
      11077: 0's = 0, 1's = 4
      11073: binary write to stdout OK
      11073: 0's = 1, 1's = 6
      11070: 0's = 4, 1's = 9