Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.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 如何使用不同的进程读取文件?_C_Signals_Fork_Semaphore - Fatal编程技术网

C 如何使用不同的进程读取文件?

C 如何使用不同的进程读取文件?,c,signals,fork,semaphore,C,Signals,Fork,Semaphore,我想使用不同的进程读取文件,但当我尝试第一个创建的子进程读取所有文件时,其他进程无法读取该文件。例如,我创建了3个不同的进程,分别有101102和103个进程ID a从=101读取。 b从=101读取。 c从=101读取。 d从=101读取 但我想这样读 a从=101读取。 b读取自=103。 c从=102读取。 d从中读取=103 我试图用信号量和互斥来解决这个问题,但我做不到。你能帮帮我吗 int i=0, pid; char buffer[100]; for(i=0; i<3; i

我想使用不同的进程读取文件,但当我尝试第一个创建的子进程读取所有文件时,其他进程无法读取该文件。例如,我创建了3个不同的进程,分别有101102和103个进程ID

a从=101读取。
b从=101读取。
c从=101读取。
d从=101读取

但我想这样读

a从=101读取。
b读取自=103。
c从=102读取。
d从中读取=103

我试图用信号量和互斥来解决这个问题,但我做不到。你能帮帮我吗

int i=0, pid;
char buffer[100];

for(i=0; i<3; i++){
    pid = fork();
    if(pid == 0){
        sem_wait(&mutex); // sem_t mutex is global.           
        while(read(fd,&buffer[j],1) == 1){
            printf("%c read from = %d\n",buffer[j],getpid());
            j++;
        }
        sem_post(&mutex);
        exit(0);
    }
    else{
        wait(NULL);
    }
}
inti=0,pid;
字符缓冲区[100];

对于(i=0;i而言,问题在于,即使每个进程都有自己的文件描述符,但这些文件描述符都共享相同的打开文件描述(“描述符”!=“描述”),读取位置存储在文件描述中,而不是文件描述符中。因此,当任何子项读取文件时,它会移动所有子项的文件指针

有关这方面的更多信息,请参阅POSIX规范:

没有互斥体或其他类似的小工具可以为您解决此问题-至少,不能单独解决。最简单的解决方法是在子进程中重新打开文件,以便每个子进程都有单独的打开文件描述以及自己的文件描述符。或者,每个子进程都必须使用互斥体、倒带文件、读取数据和rel完成后放松互斥。在子进程中(重新)打开文件更简单


请注意,必须在进程之间共享互斥体才能使其相关。请参阅POSIX规范。该规范未使用默认互斥体属性值进行设置。

您存在两个问题,这两个问题阻碍了您看起来想要的内容,并将导致(仅)第一个子级读取整个文件

  • 父进程在创建子进程后立即等待每个子进程,然后再派生更多子进程。因此,在创建第一个子进程后,它将等待该子进程退出循环并创建第二个子进程。要解决此问题,需要有两个循环父进程——第一个循环只创建子进程,第二个循环等待它们:

      for (...) {
          if (fork() == 0) {
              // run the child
              exit(0); } }
      for (...)
          wait(NULL);  // wait for a child
    
  • 您的读取循环位于sem_wait/sem_post内。因此,第一个子级将获取互斥体,然后在释放互斥体之前继续读取整个文件。后续子级在文件完全读取之前将不会获取互斥体,因此他们将看到自己处于EOF并退出。要解决此问题,您需要将sem_wait/sem_post调用移动到while循环:

      while (!done) {
          sem_wait(&mutex);
          if (read(...) == 1) { ...
          } else {
              done = true; }
          sem_post(&mutex); }
    
您甚至可能根本不需要信号量——内核将同步不同进程之间的读取,因此每个字节将由一个子级读取。这将允许子级并行进行(处理字节),而不是一次只允许一个子级运行


当然,即使使用上述方法,一个孩子可能会在另一个孩子开始运行和处理字节之前处理许多字节,因此如果处理速度快且字节数少,那么第一个孩子可能仍然会消耗掉所有字节。

我试着用信号量和互斥来解决这个问题。您肯定需要使用原语l进行某种形式的同步类似于这些。所以请显示您尝试的代码。@kaylum我在使用sam_post(&mutex)之前和之后使用了sem_wait(&mutex)。不幸的是,我对互斥和信号量缺乏经验。我正在尝试学习。请在您的帖子中使用您尝试的同步代码进行更新,并给出其确切行为。但我想这样读。请澄清您所说的“像那样”是什么意思。您试图实现的具体顺序是什么?仅从示例中不清楚。
while(read(fd,&buffer[j],1)==1)
该循环位于关键部分内。如果您只想读取一个字符,然后给另一个进程一个机会,则需要将sem操作移动到循环内,以便它等待并锁定每个字符。OP似乎希望有一个共享的文件位置,以便文件的每个字节恰好由一个子级读取。因此,他们不能在每个子级中重新打开文件,因为这会导致每个子级独立读取。这是一种可能性,@chrisdd,在这种情况下,每个子级都需要一次读取一个字符,当遇到换行符、空格或其他非数字字符时停止。他们还需要就如何进行协调达成一致,以便t进程按创建的顺序读取。一种选择是让每个子进程在读取其编号后创建一个新的子进程。这避免了许多同步问题。