序言
mkfifo用于创建有名管道(named pipe),在文件系统中以管道文件的形式存在
所以可用于进程与进程间,线程与线程间通信
管道特点:
1.有收发双方才能建立通信
2.收发阻塞
代码
fifo_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#define SERVER_FIFO "/tmp/fifo_common"
#define CLIENT_FIFO_TEMPLATE "/tmp/fifo_client.%ld"
#define CLIENT_FIFO_NAME_LEN (sizeof(CLIENT_FIFO_TEMPLATE) + 20)
#define DEBUG_MSG(msg) do{ \
fprintf(stdout,"[file:%s],[function:%s],[line:%d],%s\n",__FILE__,__FUNCTION__,__LINE__,msg); \
}while(0);
// client->server
struct request
{
pid_t pid;
int requset_num;
};
// server->client
struct response
{
int response_num;
};
int main(int argc, char *argv[])
{
char client_fifo[CLIENT_FIFO_NAME_LEN];
int server_fd;
int client_fd;
int dummy_fd;
struct request req;
struct response res;
umask(0);
if (-1 == mkfifo(SERVER_FIFO, S_IRUSR | S_IWUSR | S_IWGRP) && errno != EEXIST)
{
DEBUG_MSG("mkfifo error");
exit(EXIT_FAILURE);
}
if (-1 == (server_fd = open(SERVER_FIFO, O_RDONLY)))
{
DEBUG_MSG("open error");
exit(EXIT_FAILURE);
}
if (-1 == (dummy_fd = open(SERVER_FIFO, O_RDONLY)))
{
DEBUG_MSG("open error");
exit(EXIT_FAILURE);
}
if (SIG_ERR == signal(SIGPIPE, SIG_IGN))
{
DEBUG_MSG("signal error");
exit(EXIT_FAILURE);
}
for (;;)
{
if (read(server_fd, &req, sizeof(struct request)) != sizeof(struct request))
{
DEBUG_MSG("error reading request, discarding");
continue;
}
printf("server: client-pid = %ld\n", req.pid);
snprintf(client_fifo, CLIENT_FIFO_NAME_LEN, CLIENT_FIFO_TEMPLATE, (long)req.pid);
if (-1 == (client_fd = open(client_fifo, O_WRONLY)))
{
DEBUG_MSG("open client error, continue");
continue;
}
res.response_num = req.requset_num + 1;
if (write(client_fd, &res, sizeof(struct response)) != sizeof(struct response))
DEBUG_MSG("write to client error");
if (-1 == close(client_fd))
DEBUG_MSG("close client fd error");
}
exit(EXIT_SUCCESS);
}
fifo_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#define SERVER_FIFO "/tmp/fifo_common"
#define CLIENT_FIFO_TEMPLATE "/tmp/fifo_client.%ld"
#define CLIENT_FIFO_NAME_LEN (sizeof(CLIENT_FIFO_TEMPLATE) + 20)
#define DEBUG_MSG(msg) do{ \
fprintf(stdout,"[file:%s],[function:%s],[line:%d],%s\n",__FILE__,__FUNCTION__,__LINE__,msg); \
}while(0);
// client->server
struct request
{
pid_t pid;
int requset_num;
};
// server->client
struct response
{
int response_num;
};
static char client_fifo[CLIENT_FIFO_NAME_LEN];
static void remove_fifo(void)
{
unlink(client_fifo);
}
int main(int argc, char *argv[])
{
int server_fd;
int client_fd;
struct request req;
struct response res;
umask(0);
snprintf(client_fifo, CLIENT_FIFO_NAME_LEN, CLIENT_FIFO_TEMPLATE, (long)getpid());
if (-1 == mkfifo(client_fifo, S_IRUSR | S_IWUSR | S_IWGRP) && errno != EEXIST)
{
DEBUG_MSG("mkfifo error");
exit(EXIT_FAILURE);
}
if (0 != atexit(remove_fifo))
DEBUG_MSG("atexit error");
req.pid = getpid();
req.requset_num = 9;
if (-1 == (server_fd = open(SERVER_FIFO, O_WRONLY)))
{
DEBUG_MSG("open error");
exit(EXIT_FAILURE);
}
if (write(server_fd, &req, sizeof(struct request)) != sizeof(struct request))
DEBUG_MSG("write to server error");
if (-1 == (client_fd = open(client_fifo, O_RDONLY)))
{
DEBUG_MSG("open client error");
exit(EXIT_FAILURE);
}
if (read(client_fd, &res, sizeof(struct response)) != sizeof(struct response))
{
DEBUG_MSG("error reading response \n");
exit(EXIT_FAILURE);
}
printf("%d\n", res.response_num);
exit(EXIT_SUCCESS);
}