/**
* IPC refers to inter-process communication. Three of them are called IPC, namely message queue, semaphore, and shared storage.
* Create an IPC structure (call msgget \ semget \ shmget) and specify a key. The key data type is the basic system data type key_t, and the key is changed from the kernel to the identifier.
* The following figure shows the Message Queue msgget.
*/
/**
* Advantages and Disadvantages: the IPC structure works within the system, and there is no access count. For example, if a process creates a message queue, which contains several messages,
* Then terminate, but the message queue and its content will not be deleted. They will remain in the system until the following conditions occur:
* A process calls msgrcv or msgctl to read or delete a message queue, or a process executes the ipcrm command to delete a message queue,
* Or the system that is restarting deletes the message queue. Compared with the MPs queue, the MPs queue is completely deleted when the process of the last access MPs queue stops.
* For FIFO, although the name of the last referenced FIFO process is retained in the system until it is explicitly deleted, however, the data that is left in the FIFO is deleted at this time, so it is in vain.
* Another problem with xsi ipc is that these IPC structures have no names in the file system and we cannot use functions that use the file system to access them or modify their attributes.
* To support them, we have to add more than a dozen new system calls (msgget, semop, shmat). We cannot use the ls command to see IPC objects, nor use the rm command to delete them,
* You cannot use the chmod command to modify their access permissions. So I had to add new commands ipcs and ipcrm.
*/
# Include <sys/types. h>
# Include <unistd. h>
# Include <signal. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <sys/ipc. h>
# Include <sys/msg. h>
# Include <pthread. h>
# Define MY_KEY 8800811 // need to change
# Define SERVER_ID 2
# Define max_buckets 200
Void sigend (int );
// Message structure
Struct mymsg {
Long mtype;
Long pid;
Char buf [MAX_BUF]; // the size of the shared memory is specified here = MAX_BUF + 8
};
Int msgid;
Bool isWorking = true;
# Define SERVER_TYPE 5555
# Define CLIENT_TYPE 6666
// Receives data in blocking mode.
Void * RunRecvData (void * pVoid)
{
// Specify the receiving type -- the content of the corresponding sending structure mymsg. mtype
Long * typ = (long *) pVoid;
Struct mymsg msgbuf;
While (isWorking)
{
// Receives the message;
Msgrcv (msgid, & msgbuf, sizeof (struct mymsg), * typ, 0 );
Printf ("recv data: % s, type = % ld, pid = % ld \ n", msgbuf. buf, msgbuf. mtype, msgbuf. pid );
}
Return NULL;
}
Int main3 (void)
{
Pthread_t pidRecv;
Struct mymsg msgbuf; // define a Structure Variable
// Create a new message queue
If (msgid = msgget (MY_KEY, IPC_CREAT | IPC_EXCL | 0666) <0)
{
// Creation failed, already exists, get the message id directly, get the existing Message Queue
Msgid = msgget (MY_KEY, 0666 );
Printf ("Act as client, ask question and wait answer! Msgid = % d \ n ", msgid );
Printf ("To end this process, enter end as input question. \ n ");
Pid_t pid = getpid ();
Long type = SERVER_TYPE;
Pthread_create (& pidRecv, NULL, RunRecvData, & type );
// I/O interrupt
Printf ("Input question in one line: \ n ");
Fgets (msgbuf. buf, sizeof (struct mymsg)-2 * sizeof (long)-1, stdin );
While (strcmp (msgbuf. buf, "end \ n "))
{
// Obtain the service process number
Msgbuf. mtype = CLIENT_TYPE; // SERVER_ID;
// Obtain the process ID of the current process
Msgbuf. pid = getpid ();
// Send a message;
Msgsnd (msgid, & msgbuf, sizeof (struct mymsg)-sizeof (long), 0 );
Printf ("Input question in one line: \ n ");
Memset (msgbuf. Buf, 0, sizeof (msgbuf. BUF ));
Fgets (msgbuf. Buf, sizeof (struct mymsg)-2 * sizeof (long)-1,
Stdin );
}
}
Else
{
// Set the corresponding action of a signal, sigend Delete the tag
Signal (SIGINT, sigend );
Signal (sigterm, sigend );
Printf ("act server !!! Wait question and give answer. msgid = % d \ n ", msgid );
Printf ("To end this process, try Ctrl + C or use kill. \ n ");
Long tmpId = CLIENT_TYPE;
Pthread_create (& pidRecv, NULL, RunRecvData, & tmpId );
While (1)
{
Memset (msgbuf. buf, 0, sizeof (msgbuf. buf ));
Fgets (msgbuf. buf, sizeof (struct mymsg)-2 * sizeof (long)-1,
Stdin );
Msgbuf. mtype = SERVER_TYPE; // msgbuf. pid;
Msgbuf. pid = getpid ();
// Send a message;
Msgsnd (msgid, & msgbuf, sizeof (struct mymsg)-sizeof (long), 0 );
}
}
}
Void sigend (INT sig)
{
// Manipulate a message queue;
// Ipc_rmid: removes the Message Queue from the system kernel.
// Ipc_stat: Read the data structure msqid_ds of the message queue and store it in the address specified by BUF. Can be directly copied to reduce memory Replication
// Ipc_set: set the value of the ipc_perm element in the msqid_ds data structure of the message queue. This value is taken from the Buf parameter.
If (0 = msgctl (msgid, ipc_rmid, 0 ))
Printf ("msgctl: Success \ n ");
Else {
// Print the error message
}
Exit (0 );
}