I''m trying to use named pipe in Linux, using mkfifo. Below are codes for sender / reader
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define MSG_SIZE 100
//SENDER
int main() {
char msg[MSG_SIZE] = "FIFO is for first-in, first-out.";
int fd;
int cnt;
if(fd = open("./hello", O_RDWR) < 0) { //fifo acts as a typical file
perror("Failed to make fifo : ");
printf("Error : %d\n", errno);
exit(1);
}
int len = strlen(msg) 1;
while(1) {
if(write(fd, msg, len) == -1) {
perror("Failed to write into fifo : ");
exit(1);
}
else{
printf("Succeed to write msg!");
break;
}
}
sleep(1);
return 0;
}
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MSG_SIZE 100
//READER
int main() {
char msg_rc[MSG_SIZE];
int fd;
if(access("./hello",F_OK) == 0) {
fd = open("./hello", O_RDWR);
if(fd < 0) {
perror("Failed to open fifo : ");
exit(1);
}
}
else {
if(fd = mkfifo("./hello", O_RDWR) < 0) {
perror("Failed to open fifo : ");
exit(1);
}
}
printf("Waiting for fifo update");
while(1) {
if(read(fd, msg_rc, MSG_SIZE) == -1) {
perror("Failed to read from fifo : ");
exit(1);
}
printf("Read msg : %s\n", msg_rc);
break;
}
return 0;
}
When I used these codes,
% ./fifoSender FIFO is for first-in, first-out.Succeed to write msg!%
% ./fifoReader
fifoSender shows msg, and fifoReader shows no msg, which are not desirable behavior. Any help is needed. Thx in advance!
CodePudding user response:
Here is the working code,
// sender
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define PIPE_NAME "./hello"
int main(int argc, char *argv[])
{
const char *message = "FIFO is for first-in, first-out\n";
// Open the pipe for writing
int pipe_fd = open(PIPE_NAME, O_WRONLY);
if (pipe_fd < 0) {
perror("open");
exit(1);
}
// Write data to the pipe
while(1){
int n = write(pipe_fd, message, strlen(message));
if (n < 0) {
perror("write");
exit(1);
}
sleep(1);
}
// Close the pipe
close(pipe_fd);
return 0;
}
//receiver
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define PIPE_NAME "./hello"
int main(int argc, char *argv[])
{
// Create the named pipe
mknod(PIPE_NAME, S_IFIFO | 0666, 0);
// Open the pipe for reading
int pipe_fd = open(PIPE_NAME, O_RDONLY);
if (pipe_fd < 0) {
perror("open");
exit(1);
}
// Read data from the pipe
char buffer[1024];
while(1){
int n = read(pipe_fd, buffer, sizeof(buffer));
if (n < 0) {
perror("read");
exit(1);
}
// Print the data that was read
printf("Received: %.*s\n", n, buffer);
}
// Close the pipe
close(pipe_fd);
return 0;
}
CodePudding user response:
The main problem is these two lines
if(fd = open("./hello", O_RDWR) < 0) {
if(fd = mkfifo("./hello", O_RDWR) < 0) {
They don't do what you think they do.
Firstly, O_RDWR
is a wrong argument for mkfifo
. It expects Unix file permissions mask, such as S_IRWU"S_IRWG|S_IRWO
, or just 0666
.
Secondly and most importantly, since the priority of =
is lower than that of <
, they are parsed like this:
if(fd = (open("./hello", O_RDWR) < 0)) {
Now, when open("./hello", O_RDWR)
is less than 0 (which is highly likely, given that it is either never created or created with an incorrect mode
), fd
becomes 1, which is the standard output file descriptor.
The correct incantation is
if((fd = open("./hello", O_RDWR)) < 0) { // note () around assignment
if((fd = mkfifo("./hello", 0666)) < 0) {
There are several more subtle shortcomings.