Home > Mobile >  named pipe Linux
named pipe Linux

Time:01-04

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.

  • Related