读取和写入操作得到错误的 fd 并且没有这样的文件

Read and Write operations get bad fd and no such file

我有这个C程序。 我有两个进程,父子,并使用信号量使它们一次同步一个。 父亲必须写 (n) 个数字,在本例中是十个,总是在打开文件的第一个字节中,儿子必须读取它。 问题是,当我打印结果时,写入(父亲)的文件描述符错误,而读取(儿子)则没有这样的文件。 你能帮我吗??谢谢

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define FILENAME "test.txt"
#define MUTEX "/mutex"
#define READ "/read"
#define WRITE "/write"

int main(int argc, char *argv[]){
    int i, pid, n=10, fd, x;
    int nread, nwrite;
    char c = 'a';
    sem_t *mutex, *reader, *writer;

    //fd = open(FILENAME, O_CREAT | O_TRUNC, 0666);
    mutex = sem_open(MUTEX, O_CREAT, 0666, 1);
    reader = sem_open(READ, O_CREAT, 0666, 0);
    writer = sem_open(WRITE, O_CREAT, 0666, 1);
    pid = fork();
    fd = open(FILENAME, O_CREAT | O_TRUNC, 0777);
    if(fd < 0){
        perror("Open FILE error");
        exit(-1);}
    if(pid == 0){   // son
        do{
            sem_wait(reader);    // si può leggere???
            sem_wait(mutex);
            lseek(fd, 0, SEEK_SET);
            nread = read(fd, &x, sizeof(int));
            if(nread <=0)
                perror("Read error");
            printf("Son has read (%d byte) = %d\n", nread, x);
            fflush(NULL);
            sem_post(mutex);
            sem_post(writer);
        }
        while(x != (n-1));
        exit(0);
    }
    else{
        for(i=0; i<n; i++){
            sem_wait(writer);  // can I write??
            sem_wait(mutex);
            lseek(fd, 0, SEEK_SET);
            nwrite = write(fd, &c, sizeof(char));
            if(nwrite <= 0)
                perror("nwrite error");
            printf("Father has written (%d byte) %d\n", nwrite, i);
            fflush(NULL);
            sem_post(mutex);
            sem_post(reader);    // it's possible to read
        }
        //wait(NULL);
    }
    sem_unlink(MUTEX);
    sem_unlink(READ);
    sem_unlink(WRITE);
    //remove(FILENAME);

    exit(0);
}

你的程序有点奇怪

首先,让 parent 和 child 进程竞相创建目标文件是自找麻烦。 parent 在 分叉之前创建并打开文件 并且(仅) child 在分叉之后打开它会更好。请注意,在那种情况下,child 应该首先关闭由 parent 打开的文件描述符(其副本)。或者,按照您的操作方式,如果 parent 打开文件,那么 child 只使用它继承的文件描述符可能就足够了,根本不需要打开文件本身。

话虽如此,parent 和 child 进程通过管道进行通信比通过物理文件进行通信更为常见。这有一个特殊的优势,即您不需要通过信号量同步访问;普通阻塞 I/O 就可以了。

此外,我没有看到您的 mutex 信号量在为您做什么。即使采用需要您手动同步写入和读取的设计,看起来您的 readerwriter 信号量也可以在没有帮助的情况下实现该目的。

重要的是,您的 parent 进程正在以 sizeof(char) 字节单位写入,而您的 child 进程正在尝试以 sizeof(int) 字节单位读取。这不太可能有你想要的结果。

此外,read()write() 函数可能 return 成功,而无需传输请求的全部字节数(除非该数字是 1 并且文件是以阻塞模式打开)。您需要通过准备使用多个 I/O 操作来传输 multi-byte 数据来解决这一问题,如有必要。

最后,最好只有一个进程来解除信号量的链接。在另一个进程仍在 运行.

时发生这种情况是可以的

首先,您打开文件时没有指定 o_flag。这实际上是未定义的行为 ("Applications shall specify exactly one of .... O_RDONLY .... O_WRONLY .... O_RDWR"),但出于实际目的意味着文件已打开 只读

因此 parent 的写操作因 EBADF 而失败。无法写入只读文件!

其次,child的错误检查不正确。 read() 可能 return 零成功,在这种情况下 perror() 咨询的 errno 不能保证有意义。您的意思是检查 return 值是否小于零,而不是小于或等于零。

您的 open() 调用正在以只读方式打开文件。你有:

fd = open(FILENAME, O_CREAT | O_TRUNC, 0777);

因为您没有明确说明 O_WRONLYO_RDWR,并且因为 O_RDONLY 的传统值为 0,所以您实际上是以只读方式打开文件。

0777 权限也值得怀疑。您不是在创建可执行文件;你不应该给文件可执行权限。在我看来,您可能不应该授予其他人对该文件的写权限。事实上,我可能会选择 0600 权限。