我有这个C程序。 我有两个进程,父亲和儿子,并使用信号量使它们同时进行同步。 父亲必须写入(n)数字,在这种情况下为10,始终在打开文件的第一个字节中,儿子必须阅读它。 问题是,当我打印结果时,我得到了写(父)的错误文件描述符,而没有读取(子)的文件。 你能帮我吗??谢谢
#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);
}
答案 0 :(得分:4)
首先,您打开了文件而未指定 o_flag 。这实际上是未定义的行为("Applications shall specify exactly one of .... O_RDONLY .... O_WRONLY .... O_RDWR"),但出于实际目的,意味着文件已打开只读。
因此父母的写操作因EBADF而失败。无法写入只读文件!
其次,孩子的错误检查不正确。成功后read()
可能会返回零,在这种情况下,由errno
咨询的perror()
不能保证有意义。您的意思是检查返回值是否小于零,而不是小于或等于零。
答案 1 :(得分:1)
您的open()
来电正在打开该文件以供读取。你有:
fd = open(FILENAME, O_CREAT | O_TRUNC, 0777);
因为您没有明确说出O_WRONLY
或O_RDWR
,并且因为O_RDONLY
的传统值为0,所以您实际上是以只读方式打开文件。
0777
权限也是可疑的。您没有创建可执行文件;你不应该给予文件可执行权限。在我的书中,您可能不应该给予其他人对该文件的写入权限。事实上,我可能会使用0600
权限。
答案 2 :(得分:0)
你的程序有点奇怪。
首先,您要通过让父进程和子进程竞争成为创建目标文件的进程来解决问题。父母最好在分叉之前创建和打开文件,并且(仅)让孩子在之后打开它。请注意,在这种情况下,子应首先关闭(其副本)父项打开的文件描述符。或者,你正在做的事情,如果父母打开文件,那么孩子可能只需使用它继承的文件描述符就足够了,而根本不打开文件本身。
说到这一点,父和子进程通过管道而不是通过物理文件进行通信会更常见。这具有特殊的优势,您不需要通过信号量同步访问;普通的阻塞I / O完成了这项工作。
此外,我没有看到你的mutex
信号量对你做了什么。即使设计需要您手动同步书写和阅读,看起来您的reader
和writer
信号量将在没有帮助的情况下实现此目的。
重要的是,您的父进程正在写入sizeof(char)
- 字节uint,而您的子进程正在尝试读取sizeof(int)
- 字节单位。这不可能得到你想要的结果。
此外,read()
和write()
函数可以成功返回,而不会传输所请求的完整字节数(除非该数字为1
并且文件在阻塞模式下打开)。如果需要,您需要考虑使用多个I / O操作来传输多字节数据。
最后,最好只有一个进程取消链接您的信号量。当其他进程仍在运行时,可以发生这种情况。