c - 在 FIFO 上读取()时如何检查 EOF
c - How to check EOF when read() on FIFO
在客户端-服务器程序中,需要在 FIFO
上检查 EOF 以获得 read()
?
问题:
- EOF in FIFO return
0
或 -1
with errno set?
- 该规则是否也适用于其他 IPC 设施?
@Update
结果还是有效,还需要继续追问。
源代码如下:
cs_fifo.h:
// fifo header
#ifndef _CS_FIFO
#define _CS_FIFO
#define CLIENT_DATA_SIZE 2
#define SERVER_DATA_SIZE 10
#define SERVER_FIFO_PATH "/tmp/server_fifo"
#define CLIENT_COUNT 3
#endif
fifo_server.c:
// client - server fifo, server part,
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "cs_fifo.h"
int fifo_server() {
int flag;
int fd;
char buf[CLIENT_DATA_SIZE];
// remove fifo, before create
remove(SERVER_FIFO_PATH);
// create fifo
mode_t mode = 0644;
if((flag = mkfifo(SERVER_FIFO_PATH, mode)) == -1) {
printf("error while mkfifo(): %s\n", strerror(errno));
return -1;
}
printf("server fifo created, path: %s\n", SERVER_FIFO_PATH);
// open for read
if((fd = open(SERVER_FIFO_PATH, O_RDONLY)) == -1) {
printf("error while open(): %s\n", strerror(errno));
exit(-1);
}
// loop to receive data from client,
while(1) {
// read from fifo
if((flag = read(fd, buf, CLIENT_DATA_SIZE)) == -1) {
printf("error while read(): %s\n", strerror(errno));
exit(0);
} else if(flag == 0) { // no data
printf("no data\n");
sleep(1);
continue;
}
// data received,
printf("receive data: %s\n", buf);
// send data back to client's fifo,
// TODO
}
// remove fifo, after finish using,
remove(SERVER_FIFO_PATH);
return 0;
}
int main(int argc, char * argv[]) {
return fifo_server();
}
fifo_client.c:
// client - server fifo, client pool part,
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "cs_fifo.h"
int fifo_client_pool() {
int flag;
int server_fd;
char data[CLIENT_DATA_SIZE];
int i = 0;
pid_t cpid;
char identity;
// open for write
if((server_fd= open(SERVER_FIFO_PATH, O_WRONLY)) == -1) {
printf("error while open(): %s\n", strerror(errno));
exit(-1);
}
// create child processes as clients,
while(i < CLIENT_COUNT) {
switch(cpid=fork()) {
case -1: // failed
printf("error while fork(): %s\n", strerror(errno));
exit(errno);
case 0: // success, child process goes here
printf("child process created, pid [%d], parent pid [%d]\n",(int)getpid(), (int)getppid());
identity = i + 65; // start from 'A'
// prepare data
data[0] = identity;
data[1] = '[=12=]';
// write to fifo
if((flag = write(server_fd, data, CLIENT_DATA_SIZE)) == -1) {
printf("[%c] error while write(): %s\n", identity, strerror(errno));
_exit(-1);
}
printf("[%c] send data to server\n", identity);
_exit(0);
break;
default: // success, parent process goes here
// sleep a while,
sleep(1);
break;
}
i++;
}
if((flag = close(server_fd)) != 0) {
printf("error while close(): %s\n", strerror(errno));
}
return 0;
}
int main(int argc, char * argv[]) {
return fifo_client_pool();
}
编译:
服务器:gcc -Wall fifo_server.c -o server
客户:gcc -Wall fifo_client_pool.c -o client_pool
执行:
首次启动服务器:./server
然后启动客户端池:./client_pool
结果:
服务器启动,并在客户端启动前阻塞。
然后客户端启动,服务器收到3个客户端各1个请求,一共3个。
然后所有客户端进程终止,然后服务器的 read() 继续 return 0
没有阻塞。
以后的问题是:
- 所有客户端终止后,服务器的
read()
不应该阻塞吗?因为它处于阻塞模式?
All 从描述符中读取,其中 read
returns 零表示 "closed" 或 "end"。
如果您有一个阻塞描述符(默认),那么 read
将在当前没有可读取的内容时阻塞。如果描述符是非阻塞的,则 read
returns -1
将 errno
设置为 EAGAIN
或 EWOULDBLOCK
如果没有任何内容可读。
在客户端-服务器程序中,需要在 FIFO
上检查 EOF 以获得 read()
?
问题:
- EOF in FIFO return
0
或-1
with errno set? - 该规则是否也适用于其他 IPC 设施?
@Update
结果还是有效,还需要继续追问。
源代码如下:
cs_fifo.h:
// fifo header
#ifndef _CS_FIFO
#define _CS_FIFO
#define CLIENT_DATA_SIZE 2
#define SERVER_DATA_SIZE 10
#define SERVER_FIFO_PATH "/tmp/server_fifo"
#define CLIENT_COUNT 3
#endif
fifo_server.c:
// client - server fifo, server part,
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "cs_fifo.h"
int fifo_server() {
int flag;
int fd;
char buf[CLIENT_DATA_SIZE];
// remove fifo, before create
remove(SERVER_FIFO_PATH);
// create fifo
mode_t mode = 0644;
if((flag = mkfifo(SERVER_FIFO_PATH, mode)) == -1) {
printf("error while mkfifo(): %s\n", strerror(errno));
return -1;
}
printf("server fifo created, path: %s\n", SERVER_FIFO_PATH);
// open for read
if((fd = open(SERVER_FIFO_PATH, O_RDONLY)) == -1) {
printf("error while open(): %s\n", strerror(errno));
exit(-1);
}
// loop to receive data from client,
while(1) {
// read from fifo
if((flag = read(fd, buf, CLIENT_DATA_SIZE)) == -1) {
printf("error while read(): %s\n", strerror(errno));
exit(0);
} else if(flag == 0) { // no data
printf("no data\n");
sleep(1);
continue;
}
// data received,
printf("receive data: %s\n", buf);
// send data back to client's fifo,
// TODO
}
// remove fifo, after finish using,
remove(SERVER_FIFO_PATH);
return 0;
}
int main(int argc, char * argv[]) {
return fifo_server();
}
fifo_client.c:
// client - server fifo, client pool part,
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "cs_fifo.h"
int fifo_client_pool() {
int flag;
int server_fd;
char data[CLIENT_DATA_SIZE];
int i = 0;
pid_t cpid;
char identity;
// open for write
if((server_fd= open(SERVER_FIFO_PATH, O_WRONLY)) == -1) {
printf("error while open(): %s\n", strerror(errno));
exit(-1);
}
// create child processes as clients,
while(i < CLIENT_COUNT) {
switch(cpid=fork()) {
case -1: // failed
printf("error while fork(): %s\n", strerror(errno));
exit(errno);
case 0: // success, child process goes here
printf("child process created, pid [%d], parent pid [%d]\n",(int)getpid(), (int)getppid());
identity = i + 65; // start from 'A'
// prepare data
data[0] = identity;
data[1] = '[=12=]';
// write to fifo
if((flag = write(server_fd, data, CLIENT_DATA_SIZE)) == -1) {
printf("[%c] error while write(): %s\n", identity, strerror(errno));
_exit(-1);
}
printf("[%c] send data to server\n", identity);
_exit(0);
break;
default: // success, parent process goes here
// sleep a while,
sleep(1);
break;
}
i++;
}
if((flag = close(server_fd)) != 0) {
printf("error while close(): %s\n", strerror(errno));
}
return 0;
}
int main(int argc, char * argv[]) {
return fifo_client_pool();
}
编译:
服务器:gcc -Wall fifo_server.c -o server
客户:gcc -Wall fifo_client_pool.c -o client_pool
执行:
首次启动服务器:./server
然后启动客户端池:./client_pool
结果:
服务器启动,并在客户端启动前阻塞。
然后客户端启动,服务器收到3个客户端各1个请求,一共3个。
然后所有客户端进程终止,然后服务器的 read() 继续 return
0
没有阻塞。
以后的问题是:
- 所有客户端终止后,服务器的
read()
不应该阻塞吗?因为它处于阻塞模式?
All 从描述符中读取,其中 read
returns 零表示 "closed" 或 "end"。
如果您有一个阻塞描述符(默认),那么 read
将在当前没有可读取的内容时阻塞。如果描述符是非阻塞的,则 read
returns -1
将 errno
设置为 EAGAIN
或 EWOULDBLOCK
如果没有任何内容可读。