读取和写入操作得到错误的 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
信号量在为您做什么。即使采用需要您手动同步写入和读取的设计,看起来您的 reader
和 writer
信号量也可以在没有帮助的情况下实现该目的。
重要的是,您的 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_WRONLY
或 O_RDWR
,并且因为 O_RDONLY
的传统值为 0,所以您实际上是以只读方式打开文件。
0777
权限也值得怀疑。您不是在创建可执行文件;你不应该给文件可执行权限。在我看来,您可能不应该授予其他人对该文件的写权限。事实上,我可能会选择 0600
权限。
我有这个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
信号量在为您做什么。即使采用需要您手动同步写入和读取的设计,看起来您的 reader
和 writer
信号量也可以在没有帮助的情况下实现该目的。
重要的是,您的 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_WRONLY
或 O_RDWR
,并且因为 O_RDONLY
的传统值为 0,所以您实际上是以只读方式打开文件。
0777
权限也值得怀疑。您不是在创建可执行文件;你不应该给文件可执行权限。在我看来,您可能不应该授予其他人对该文件的写权限。事实上,我可能会选择 0600
权限。