System v ipc:
This must be understood first, because many books or materials directly say that IPC is a shared memory, message queue, and signal set. In fact
IPC is a mechanism that provides a channel for inter-process communication. Why does it add System V?
The Process Communication IPC mechanism proposed in four versions of the system. So it is called System v ipc.
Currently, Linux supports these three mechanisms: Shared Memory, message queue, and traffic signal set.
The Linux kernel defines a struct:
Struct ipc_perm
{
Key_t key; keyword
Uid_t uid;/* valid user ID of the shared memory owner */
Gid_t GID;/* Valid group ID of the group to which the shared memory owner belongs */
Uid_t cuid;/* valid user ID of the creator of shared memory */
Gid_t cgid;/* Valid group ID of the group to which the shared memory creator belongs */
Unsigned short mode;/* permissions + shm_dest and shm_locked flag */
Unsignedshort seq;/* serial number */
};
The key is the key to identify the shared channel.
The created key is used in all three mechanisms;
Generally, the ftok function is used to create a key.
Key_t ftok (char * fname, int ID)
For example:
If (Key = ftok (".",'s ') <0)
{
Perror ("fail to ftok ");
Exit (-1 );
}
In this way, a key is generated. You can also define the key yourself, but the key defined in this way is not safe. So try to use ftok to generate the key.
The following describes three mechanisms:
The first thing to mention is the shared memory, which is the most efficient way of inter-process communication. The process can directly read and write the memory, which is very fierce and does not require any data copying.
In order to exchange information among multiple processes, the kernel sets aside a dedicated memory zone for the processes to be accessed to map them to their own private address space. This mechanism requires
It is based on absolute trust. Otherwise, some important information of the system may be used if it is placed in this memory zone.
The process does not need to be copied, so the sentence greatly improves the efficiency. Because multiple processes share a piece of memory, they also need to rely on a synchronization mechanism, such as mutex and semaphore.
Function header file:
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SHM. h>
Steps for implementing shared memory:
1. Create/enable shared memory
Int shmget (key_t key, int size, int shmflg );
Function parameters:
Key: Return Value of ipc_private or ftok
Size: the size of the shared memory.
Shmflg: Permission bit
Returned value: Successful: shared memory segment identifier
Failed-1;
2. Map the specified shared memory to the address space of the process for access.
Void * shmat (INT shmid, const void * shmaddr, int shmflg );
Function parameter: shmid: The identifier of the shared memory to be mapped.
Shmaddr: maps the shared memory to the specified address (if it is null, the system automatically completes the ing)
Shmflg: shm_rdonly shared memory read-only
Default Value: 0. The shared memory can be read and written.
Return Value: Successful, mapped address
Failed-1;
3. Undo the shared memory ing
Int shmdt (const void * shmaddr );
Function parameter: shmaddr: Address mapped to the shared memory
Function return value: Success 0, failure-1
4. Delete shared memory objects
Int shmctl (INT shmid, int cmd, struct shmid_ds * BUF );
Function parameter: shmid: The identifier of the shared memory to be operated.
CMD: ipc_stat (get object attributes)
Ipc_set (set object attributes)
Ipc_rmid (delete object)
Buf: used to save/set attributes when ipc_stat/ipc_set is specified
Returned value; success 0, error-1;
/*************************************** ** Write end *********************************** ****/
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <errno. h>
# Include <signal. h>
# Include <string. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SHM. h>
# Define n 64
Typedef struct
{
Pid_t PID;
Char Buf [N];
} SHM;
Void handler (INT signo)
{
Return;
}
Int main ()
{
Pid_t PID;
Key_t key;
Int shmid;
SHM * shmadd;
If (Key = ftok (".",'s ') <0)
{
Perror ("fail to ftok ");
Exit (-1 );
}
Signal (SIGUSR1, Handler );
If (shmid = shmget (Key, sizeof (SHM), 0666 | ipc_creat | ipc_excl) <0) // not first Process
{
If (errno = eexist)
{
Shmid = shmget (Key, sizeof (SHM), 0666 );
Shmadd = (SHM *) shmat (shmid, null, 0 );
PID = shmadd-> PID;
Shmadd-> pid = getpid ();
Kill (PID, SIGUSR1 );
}
Else
{
Perror ("fail to shmget ");
Exit (-1 );
}
}
Else // first Process
{
Shmadd = (SHM *) shmat (shmid, null, 0 );
Shmadd-> pid = getpid ();
Pause ();
PID = shmadd-> PID;
}
While (1)
{
Printf ("write to SHM :");
Fgets (shmadd-> Buf, N, stdin );
Kill (PID, SIGUSR1 );
If (strncmp (shmadd-> Buf, "Quit \ n", 5) = 0) break;
Pause ();
}
Shmdt (shmadd );
If (shmctl (shmid, ipc_rmid, null) <0)
{
Perror ("fail to shmctl ");
}
Return 0;
}
/*************************************** ********************************** *****/
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <errno. h>
# Include <signal. h>
# Include <string. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SHM. h>
# Define n 64
Typedef struct
{
Pid_t PID;
Char Buf [N];
} SHM;
Void handler (INT signo)
{
Return;
}
Int main ()
{
Pid_t PID;
Key_t key;
Int shmid;
SHM * shmadd;
If (Key = ftok (".",'s ') <0)
{
Perror ("fail to ftok ");
Exit (-1 );
}
Signal (SIGUSR1, Handler );
If (shmid = shmget (Key, sizeof (SHM), 0666 | ipc_creat | ipc_excl) <0) // not first Process
{
If (errno = eexist)
{
Shmid = shmget (Key, sizeof (SHM), 0666 );
Shmadd = (SHM *) shmat (shmid, null, 0 );
PID = shmadd-> PID;
Shmadd-> pid = getpid ();
Kill (PID, SIGUSR1 );
}
Else
{
Perror ("fail to shmget ");
Exit (-1 );
}
}
Else // first Process
{
Shmadd = (SHM *) shmat (shmid, null, 0 );
Shmadd-> pid = getpid ();
Pause ();
PID = shmadd-> PID;
}
While (1)
{
Pause ();
If (strncmp (shmadd-> Buf, "Quit \ n", 5) = 0) break;
Printf ("read from SHM :");
Printf ("% s", shmadd-> BUF );
Kill (PID, SIGUSR1 );
}
Shmdt (shmadd );
Return 0;
}
//////////////////////////////////////// //////////////////////////////////////// /////////////////////////////
//////////////////////////////////////// //////////////////////////////////////// /////////////////////////////
Message Queue:
A message queue is a type of IPC object, uniquely identified by the Message Queue ID. A message queue is a list of messages. You can add and read messages in a message queue.
Message Queue can be installed to send/receive messages.
MQ operations include creating or opening a message queue, adding a message, reading a message, and controlling a message.
1. Create or open a message queue:
Int msgget (key_t key, int flag );
Function parameter: Key key value
Flag Message Queue access permission
Function return value: ID of the successful message queue, error-1;
The number of created message queues is limited by the number of system message queues.
2. Add a message function
Int msgsnd (INT msqid, const void * msgp, size_t size, int flag );
Function parameter: msqid: ID of the Message Queue
Msgp: pointer to the message. The common message structure msgbuf is as follows:
Struct msgbuf {
Long mtype; // Message Type
Char mtext [N]; // Message Body
};
Size: the number of bytes of the sent message body.
Flag: The ipc_nowait function returns immediately if the message is not sent.
0. It is not returned until the sending is complete.
Function return value: Success 0, error-1;
3. Read the message function
Int msgrcv (INT msgid, void * msgp, size_t size, long msgtype, int flag)
Function parameters:
Msqid: ID of the Message Queue
Msgp: the buffer for receiving messages
Size: the number of bytes to receive messages.
Msgtype: 0: receives the first message in the message queue.
If the value is greater than 0, the first message type in the message queue is msgtyp.
The value is less than 0, and the type value in the received message queue is not smaller than the absolute value of msgtyp and has the smallest type value.
Flag: 0. If there is no message, the function will be blocked all the time.
Ipc_nowait. If there is no message, the process immediately returns enomsg
Function return value: the length of the received message.
Failed-1;
4. Control Message usage functions:
Int msgctl (INT msgqid, int cmd, struct msqid_ds * BUF)
Function parameters:
Msgqid Message Queue ID
CMD: ipc_stat reads the attributes of the message queue and stores them in the buffer zone of the Buf execution.
Ipc_set sets the Message Queue attributes. This value is taken from the Buf parameter.
Ipc_rmid: deletes a message queue from the system.
Buf: Message Queue Buffer
Function return value: Success 0, failure-1;
Example:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/msg. h>
# Define bfusz 512
# Define type 100
Struct msgbuf {
Long mtype;
Char mtext [bfusz];
};
Int main ()
{
Int qid, Len;
Key_t key;
Struct msgbuf MSG;
If (Key = ftok (".", 'A') =-1)
{
Perror ("ftok ");
Exit (-1 );
}
If (qid = msgget (Key, ipc_creat | 0666) =-1)
{
Perror ("msgget ");
Exit (-1 );
}
Printf ("opened queue % d \ n", qid );
If (fgets (& MSG)-> mtext, bfusz, stdin) = NULL)
{
Puts ("no message ");
Exit (-1 );
}
MSG. mtype = type;
Len = strlen (msg. mtext) + 1;
If (msgsnd (qid, & MSG, Len, 0) <0)
{
Perror ("msgsnd ");
Exit (-1 );
}
If (msgrcv (qid, & MSG, bfusz, 0, 0) <0)
{
Perror ("msgrcv ");
Exit (-1 );
}
Printf ("message is: % s \ n", (& MSG)-> mtext );
If (msgctl (qid, ipc_rmid, null) <0)
{
Perror ("msgctl ");
Exit (1 );
}
Return 0;
}
//////////////////////////////////////// //////////////////////////////////////// ///////////
//////////////////////////////////////// //////////////////////////////////////// ///////////
//////////////////////////////////////// //////////////////////////////////////// ///////////
//////////////////////////////////////// //////////////////////////////////////// ///////////
Semaphore is also called a semaphore. It is a mechanism for synchronization between different processes or different threads in the same process.
Signal lamp type:
POSIX famous signal lights
POSIX memory-based traffic signals (unknown traffic signals)
System V signal lamp (IPC object)
A System V signal lamp is a collection of one or more signal lights. Every one of them is a delayed counting signal. The POSIX signal lamp refers to a single signal lamp.
The System V signal is maintained by the kernel.
Main functions: semget, semop, semctl
Int semget (key_t key, int nsems, int semflg );
Function parameter: key value associated with the traffic signal set
Nsems: Number of signals contained in a signal set
The access permission of the semflg Traffic Signal Set is usually ipc_creat | 0666
Function return value: Success Signal Set ID
Failed-1;
Int semop (INT Semid, struct sembuf * opsptr, size_t NOPs );
Function parameter: Semid: Signal Set ID
Struct sembuf {
Short sem_num; // The signal number to be operated
Short sem_op; // 0: wait until the traffic signal value changes to 0
// 1: release resources and perform operations v
//-1: Apply for resources, P operation
Short sem_flg; // 0, ipc_nowait, sem_undo
};
NOPs: Number of signal lights to operate
Function return value: Success 0, failure-1;
Int semctl (INT Semid, int semnum, int cmd.../* Union semun Arg */)
Function parameters:
Semid: Signal Set ID
Semnum: signal number to be modified
CMD:
Getval: Get the traffic signal value.
Setval: Set the traffic signal value.
Ipc_rmid: removes the traffic signal set from the system.
Function return value: Success 0, failure-1;
Example:
/********************************* Read ***** **************************************** */
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <errno. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Include <sys/SHM. h>
Union semun {
Int val;/* value for setval */
Struct semid_ds * Buf;/* buffer for ipc_stat, ipc_set */
Unsigned short * array;/* array for getall, setall */
Struct seminfo * _ Buf;/* buffer for ipc_info
(Linux-specpacific )*/
};
# Define n 64
# Define read 0
# Define write 1
Void sem_init (INT Semid, int array [], int N)
{
Union semun Myun;
Int I;
For (I = 0; I <n; I ++)
{
Myun. Val = array [I];
Semctl (Semid, I, setval, myun );
}
Return;
}
Void PV (INT Semid, int num, int OP)
{
Struct sembuf Buf;
Buf. sem_num = num;
Buf. sem_op = op;
Buf. sem_flg = 0;
If (semop (Semid, & Buf, 1) <0)
{
Exit (0 );
}
Return;
}
Int main ()
{
Key_t key;
Int shmid, Semid;
Char * shmaddr;
Int array [] = {0, 1 };
If (Key = ftok (".",'s ') <0)
{
Perror ("fail to ftok ");
Exit (-1 );
}
If (Semid = semget (Key, 2, 0666 | ipc_creat | ipc_excl) <0)
{
If (eexist = errno)
{
Semid = semget (keys, 2, 0666 );
}
Else
{
Perror ("fail to semget ");
Exit (-1 );
}
}
Else
{
Sem_init (Semid, array, 2 );
}
If (shmid = shmget (Key, N, 0666 | ipc_creat) <0)
{
Perror ("fail to shmget ");
Exit (-1 );
}
Shmaddr = (char *) shmat (shmid, null, 0 );
While (1)
{
PV (Semid, read,-1 );
Printf ("read from SHM: % s", shmaddr );
PV (Semid, write, 1 );
}
Return 0;
}
/*************************************** ********************************** ********/
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <errno. h>
# Include <string. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Include <sys/SHM. h>
Union semun {
Int val;/* value for setval */
Struct semid_ds * Buf;/* buffer for ipc_stat, ipc_set */
Unsigned short * array;/* array for getall, setall */
Struct seminfo * _ Buf;/* buffer for ipc_info
(Linux-specpacific )*/
};
# Define n 64
# Define read 0
# Define write 1
Void sem_init (INT Semid, int array [], int N)
{
Union semun Myun;
Int I;
For (I = 0; I <n; I ++)
{
Myun. Val = array [I];
Semctl (Semid, I, setval, myun );
}
Return;
}
Void PV (INT Semid, int num, int OP)
{
Struct sembuf Buf;
Buf. sem_num = num;
Buf. sem_op = op;
Buf. sem_flg = 0;
Semop (Semid, & Buf, 1 );
Return;
}
Int main ()
{
Key_t key;
Int shmid, Semid;
Char * shmaddr;
Int array [] = {0, 1 };
If (Key = ftok (".",'s ') <0)
{
Perror ("fail to ftok ");
Exit (-1 );
}
If (Semid = semget (Key, 2, 0666 | ipc_creat | ipc_excl) <0)
{
If (eexist = errno)
{
Semid = semget (keys, 2, 0666 );
}
Else
{
Perror ("fail to semget ");
Exit (-1 );
}
}
Else
{
Sem_init (Semid, array, 2 );
}
If (shmid = shmget (Key, N, 0666 | ipc_creat) <0)
{
Perror ("fail to shmget ");
Exit (-1 );
}
Shmaddr = (char *) shmat (shmid, null, 0 );
While (1)
{
PV (Semid, write,-1 );
Printf ("write to SHM :");
Fgets (shmaddr, N, stdin );
If (strncmp (shmaddr, "Quit \ n", 5) = 0) break;
PV (Semid, read, 1 );
}
Shmdt (shmaddr );
Shmctl (shmid, ipc_rmid, null );
Semctl (Semid, 0, ipc_rmid );
Return 0;
}