In the article “Running Shell Scripts in Linux C Code to Get Their Return Values,” the concept of “anonymous pipes” was mentioned, which allows communication between parent and child processes through the use of fork. However, this is limited to communication between a parent and its child or between two child processes with the same ancestor. This article aims to discuss the implementation of communication between unrelated processes, which can be achieved using named pipes (FIFO) provided by Linux:About FIFOFIFO (First In First Out) is a special type of file that has a corresponding path in the file system. When one process opens this file in read mode and another process opens it in write mode, the Linux kernel establishes a pipe between these two processes. The relevant function prototypes are as follows:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
int mknode(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0 );
Here, filename is the file path of the FIFO named pipe, and mode specifies the corresponding permissions (where S_IFIFO specifically marks FIFO), and dev represents the FIFO device (denoted by 0).Below is an example (test_fifo.c):
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main() {
int res = mkfifo("/tmp/my_fifo", 0777);
if (res == 0) {
printf("FIFO created\n");
}
return 0;
}
We compile this program with the following command:
gcc -o test_fifo test_fifo.c
Then we execute it with the following command:
./test_fifo
After that, we can use the ls command to view the created pipe file as follows:
$ ls -lF /tmp/my_fifo
prwxr-xr-x 1 root root 0 05-08 20:10 /tmp/my_fifo|
As seen, the first character ‘p’ indicates that this file is a pipe, and the last ‘|’ symbol is the identifier presented by the -F parameter recognizing it as a FIFO pipe.FIFO Communication Between Two ProcessesProcess 1 creates a named pipe file for reading; Process 2 opens the named pipe for writing. The corresponding reference code is as follows:Process 1 (Process1.c):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
char buf[100] = {};
int res = mkfifo("/tmp/test.fifo", 0666);
if(res == -1) {
perror("mkfifo");
exit(-1);
}
int fd = open("/tmp/test.fifo", O_RDONLY);
if(fd == -1) {
perror("open");
exit(-1);
}
while(1) {
res = read(fd, buf, sizeof(buf));
if(res <= 0)
break;
printf("buf = %s\n", buf);
}
close(fd);
return 0;
}
Process 2 (Process2.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
char buf[100] = {};
int fd = open("/tmp/test.fifo", O_WRONLY);
if(fd == -1) {
perror("open");
exit(-1);
}
while(1) {
printf("Please enter:");
fgets(buf, sizeof(buf), stdin);
write(fd, buf, sizeof(buf));
}
close(fd);
return 0;
}
Thus, we have understood the process of implementing inter-process communication using FIFO in Linux C programming, and a set of communication protocol rules can be defined based on actual needs to achieve more complex functionalities.