Pipeline and message queue for interprocess communication
The Conduit
Basic knowledge
-
The Conduit
Like real water pipes, water is like data.
Pipeline is a half-duplex communication mode
Data can only flow in one direction, and can only be used between processes with common ancestors.
Introduction to Functions
int pipe(int fd[2])
Function: Create Pipeline
Parameter fd correlation:
One reader: fd[0]
A Writer End: fd[1]
Header file <unistd.h>-
int read(int fd, void *buf, int count);
Function: Read pipeline data from reader specified by parameter fd to buffer buf of count size, and return the actual number of bytes read.
parameter
fd: Pipeline Reader
buf: Buffer to save read data
count: Number of bytes read -
int write(int fd, void *buf, int count);
Function: Remove count bytes from buffer buf to pipeline at the write end specified by parameter fd, and return the number of bytes actually written.
parameter
fd: Pipeline Writing End
buf: Buffer, data to be written to the pipeline
count: The number of bytes written
Exercise content
1. Parent process creates pipes and two child processes p 1 and p2 2. Subprocess p1 opens a given file (if not, creates a file), writes data to the file, closes the file, and then writes a message "ok" to the pipeline to inform process p2 that it can read the contents of the file. 3. Subprocess p2 reads messages through a pipeline. If the message is "ok", it opens the file, reads the contents of the file, outputs them to the screen and closes the file.
Implementation code
/*2.Using Pipeline to Realize Interprocess Communication
Write a program, the parent process creates a pipeline and two child processes p1 and p2
Subprocess p1 opens a given file (if not, creates a file), writes data to the file, closes the file, and then writes a message "ok" to the pipeline to inform process p2 that it can read the contents of the file.
The sub-process p2 reads the message through the pipeline. If the message is "ok", it opens the file, reads the contents of the file, and outputs it to the channel screen.**/
//Pipeline is a half-duplex communication mode
//Data can only flow in one direction and can only be used between processes with common ancestors.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h> //Header file required by pipeline
#include <string.h>
//# include <mem.h>//memset() function
#include <fcntl.h>
#define BUFFER_SIZE 1024
int write_file() //Write the content into the document.
{
int f=open("a.txt",O_WRONLY|O_CREAT,0660);//Open the file for the specified path, if there is no automatic creation
//f is a file pointer
if(f==-1) //Failed to open
{
printf("open file error !\n");
return 0;
}
char buffer[]="this is a file";//Written into a document
write(f,buffer,sizeof(buffer));
//Writer specified to parameter f fetches bytes of specified size from the cache buf into the pipeline
//Return value is the number of bytes actually written
close(f);//Close files
return 1;
}
int read_file(char *buffer)
{
int f=open("a.txt",O_RDONLY,0660);//Open the file for the specified path, if there is no automatic creation
if(f==-1)//fail to open file
{
printf("open file error !\n");
return 0;
}
int numofchar=read(f,buffer,BUFFER_SIZE); //f stands for reading end
//I don't know how much valid data there is in the buffer, so read out the contents of the buffer size.
//Read pipeline data from the reader specified in parameter f to the buffer buf specified in size
//Returns the number of bytes actually read
close(f);
return numofchar;
}
int main(int argc,char *argv[])
{
int fd[2]; //Create the read and write end of the pipeline (fd [0] read, FD [1] write)
if(pipe(fd)<0)//Creating Pipelines
{
perror("pipe");//Error output function, showing error 0 when there are no errors
exit(0);
}
char mas[100];
int n;
memset(mas,0,sizeof(mas)); //Clear buf content to 0
//Setting a byte to a specified value
//build son
pid_t p1;
p1=fork();
if(p1<0) //Failure to create process
{
fprintf(stderr,"fork failed");
exit(-1);
}
else if(p1==0)//son
{
//Subprocess p1 opens the given file (if not, creates the file)
//Write data to the file, close the file, and write a message "ok" to the pipeline.“
//The purpose is to notify process p2 that the file content is readable
if(write_file()) //Call Write File Function
{
close(fd[0]); //close read
char *massage = "ok";
write(fd[1],massage,100); //Write pipeline messages
//ok is written in fd [1].
}
}
else //father
{
pid_t p2;
p2=fork();
if(p2<0)//Failure to create process
{
fprintf(stderr,"fork failed");
exit(-1);
}
else if(p2==0)//son
{
close(fd[1]); //close write
read(fd[0],mas,sizeof(mas));// Read the message from the reader
if(!strcmp(mas,"ok")) // is "ok" or no
{
char data[BUFFER_SIZE];
int n =read_file(data); //Read the contents of the file and store them in data
printf("data of file is : %s. \n",data);//Print out
}
}
else //father
{
exit(0);
}
}
return 0;
}
Message queue
Message queues provide a way to send block data from one process to another.
Each data block is considered to have a type, and the receiving process can receive different types of data blocks independently.
Basic knowledge
-
Message queue
Link tables for messages, abbreviated as queues
Identifier: Queue ID
The structure of messages in the queue:
Introduction to Functions
int msgget(key_t key, int flag)
Header file: <sys/msg.h>
Function: Open a queue or create a new queue
Return value: a queue id
Parameters:
Key: An identifier, also known as a key. It can be understood as the only port to get the key method:
Function ftok(const char* path,int id)
The ftok function generates a key from a path name and item id
For example: key = ftok(".",'t');
flag: Control tag, specifying how to create it
For example: 0660 | IPC_CREAT-
int msgsnd(int msqid, const void * ptr, size_t nbytes, int flag)
Header file: <sys/msg.h>
Function: Write a message to the message queue, that is, send a message.
Parameters:
msqid: queue id
ptr: Structural pointer to the message to be sent, pointing to the address of the message
nbytes: Number of bytes sent
Flag: Control flag, generally designated IPC_NOWAIT int msgrcv(int msqid, const void * ptr, size_t nbytes ,long type, int flag) ;
Header file: <sys/msg.h>
Function: Read messages from message queues, that is, receive messages.
Parameters:
msqid: queue id
ptr: The received message is saved to the message structure to which the pointer points
nbytes: Number of bytes received
type
== 0 returns the first message of the queue
> 0 returns the first message of type in the queue
<0 Returns messages less than or equal to the absolute value of type
Flag: Control flag, generally designated IPC_NOWAIT
Exercise content
Parent processes create message queues and two child processes p1 and p2 Subprocess p1 opens a given file (if not, creates a file), writes data to the file, closes the file, and then writes a message "ok" to the message queue to inform process p2 that it can read the contents of the file. Subprocess p2 reads the message from the message queue. If it receives the message "ok", it opens the file, reads the content of the file, and outputs it to the screen of the channel, closes the file.
Implementation code
/*Parent processes create message queues and two child processes p1 and p2
Subprocess p1 opens a given file (if not, creates a file), writes data to the file, closes the file, and then writes a message "ok" to the message queue to inform process p2 that it can read the contents of the file.
Subprocess p2 reads the message from the message queue. If it receives the message "ok", it opens the file, reads the content of the file, and outputs it to the screen of the channel, closes the file.
*/
#include<stdio.h>
#include<sys/msg.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#define NUM 100
//Message Communication
//Message queues provide a way to send block data from one process to another.
//Each data block is considered to have a type, and the receiving process can receive different types of data blocks independently.
struct mymsg
{
long mytype; //Storage message type
char mytext[NUM];//Store message content
};
int main()
{
FILE *f; //field name pointer
pid_t p1,p2;// Two processes
key_t key;
key = ftok(".", 't');
//Format Conversion Function of System IPC Key Values
char s[20];
int mgsid;
if((mgsid=msgget(key,IPC_CREAT|0666))==-1)//Open a queue or create a new queue
{
printf("creat error\n");
return -1;
}
p1=fork();
if(p1<0)
{
fprintf(stderr,"fork failed");
exit(-1);
}
else if(p1==0)
{
printf("p1 pid is:%d\n",getpid()); //p1id
printf("sending the massage...\n");
sleep(1); //This thread hibernates for 1 millisecond
struct mymsg msg1;
msg1.mytype=getppid(); //Parent process id
if((f=fopen("hello.txt","w"))==NULL) //fail to open file
{
printf("the file %s not open\n","hello.txt");
return ;
}
fputs("hello!",f);//Send a character to a stream
fclose(f);
strcpy(msg1.mytext,"ok");
if(msgsnd(mgsid,&msg1,sizeof(msg1.mytext),0)<0)//Write a message to a message queue, that is, send a message.
{
printf("sending error!\n");
exit(-1);
}
else
{
printf("complete sending !\n");
exit(0);
}
}
else
{
wait(NULL);
p2=fork();
if(p2<0)
{
printf("fork creat error!\n");
exit(1);
}
else if(p2==0)
{
printf("p2 pid is:%d\n",getpid());
printf("Receiving the massage...\n");
sleep(1);//This thread hibernates for 1 millisecond
struct mymsg msg2;
msg2.mytype=getppid();
if(msgrcv(mgsid,&msg2,NUM,getppid(),0)<0)//Reading a message from a message queue, that is, receiving a message
{
printf("receving error!!!\n");
exit(1);
}
else
{
printf("complete receving \n");
if(strcmp("ok",msg2.mytext)==0)
{
if((f=fopen("hello.txt","r"))==NULL)
{
printf("the file %s no opend.\n","hello.txt");
return;
}
while((fgets(s,20,f))!=NULL)//Read a line or specify a character from a stream
{
printf("the massage is:%s\n",s);
}
fclose(f);
}
}
}
else
{
wait(NULL);
exit(0);
}
}
return 0;
}
The content of this blog is introduced here, welcome to correct!