Inter-process communication (9), inter-process communication

Source: Internet
Author: User

Inter-process communication (9), inter-process communication

1. Preface all examples in this article, based on RHEL6.5 platform (linux kernal: 2.6.32-431. el6.i686 ).

2. the introduction of shared memory is also an IPC, which is currently the fastest IPC. It is used to map the same memory zone to the address space of different processes sharing it, in this way, the communication between these processes does not need to pass through the kernel. You only need to perform operations on the processes in the shared memory area.

The biggest advantage of communication between the shared memory and other processes is that data is replicated only twice, from the input file to the shared memory area, and from the shared memory area to the output file. Others require four copies: the server reads the input file into its own process space, and then writes it to the MPs queue or message queue from its own process space; the customer process reads data from the pipeline/message queue to its own process space, and finally outputs the data to the file specified by the customer.

To use shared memory, follow these steps:
1. Open up a shared memory shmget ()
2. allow this process to use a shared memory shmat ()
3. Write/read
4. prohibit this process from using this shared memory shmdt ()
5. Delete the shared memory shmctl () or use the command line ipcrm

The Posix shared memory (Click here) has been introduced in the previous article. The System V shared memory zone is similar in concept to the Poisx shared memory zone, posix shared memory zone is used to call shm_open to create a shared memory zone and call mmap to map the memory zone, the System V shared memory zone calls shmget to create a shared memory zone and then calls shmat to map the memory zone.

For each System V shared memory zone, the kernel maintains a shmid_ds data structure. The definition in Linux 2.6.32 is as follows. For details, see/usr/include/sys/shm. h.

<Sys/shm. h> typedef unsigned long int shmatt_t; // data type of the number of processes connected to the shared memory area struct shmid_ds {struct ipc_perm shm_perm; // operation permission struct size_t shm_segsz; // maximum number of bytes of the shared storage segment _ time_t shm_atime; // time of last shmat () _ time_t shm_dtime; // time of last shmdt () _ time_t shm_ctime; // time of last change by shmctl () _ pid_t shm_cpid; // pid of creator _ pid_t shm_lpid; // pid of last shmop shmatt_t shm_nattch; // number of processes connected to the shared memory area // reserved field unsigned long int _ unused1; unsigned long int _ unused2; unsigned long int _ unused3; unsigned long int _ unused4; unsigned long int _ unused5 ;};

3. Create shared memory shmget

# Include <sys/shm. h> int shmget (key_t key, size_t size, int shmflg); // the shared memory identifier is returned for success, and-1 is returned for failure.

The shmget function is used to create or open a shared memory area object. If shmget is successfully called, a shared memory area identifier is returned for other shared memory area operation functions.

Key: the key value used to create the shared memory zone. This is discussed before when other System IPC instances are created. System IPC has a key as the external identifier of IPC, the descriptor returned after successful creation is used as the internal identifier of the IPC. The main purpose of the key is to merge different processes in the same IPC.
It is the identifier of the shared memory. For inter-process communication of the parent-child relationship, this identifier is replaced by IPC_PRIVATE.

Key can be generated in three ways:
· A value agreed by different processes;
· Call the ftok () function with the same path name and Project ID to generate a key;
· You can also set IPC_PRIVATE to create a unique IPC object and pass the returned descriptor to other processes in some way;

Size: specify the size of the shared memory area, in bytes. If the actual operation is to create a shared memory area, you must specify a non-0 value. If the actual operation is to access an existing shared memory area, the size should be 0. Because all linux memory allocation operations are in the unit of pages. Therefore, if a process requests only one piece of memory with only one byte, the memory will be allocated a whole page (the default size of one page on the i386 machine is PACE_SIZE = 4096 bytes, the size of the newly created shared memory is actually the page size adjusted from the size parameter. That is, if the size is 1 to 4096, the size of the actually applied shared memory is 4 K (one page); 4097 to 8192, the size of the actually applied shared memory is 8 K (two pages), and so on.

Shmflg: Specifies the flag for creating or opening a message queue and the read/write permission (mode member in ipc_perm ). We know that System v ipc defines its own operation flag and permission setting flag, and it is passed through this parameter, which is different from the open function, the third parameter of the open function is the permission flag used to pass files. The operation flag of System v ipc includes IPC_CREAT and IPC_EXCL.
-- IPC_CREAT: if the shared memory does not exist, a shared memory is created. Otherwise, the operation is enabled.
-- IPC_EXCL: a new shared memory is created only when the shared memory does not exist. Otherwise, an error occurs.
If you use IPC_CREAT separately, the shmget () function either returns an existing shared memory operator or a new shared memory identifier.
If IPC_CREAT and IPC_EXCL are used together, shmget () returns a new shared memory identifier. If the shared memory already exists,-1 is returned.
The IPC_EXCL mark does not make much sense, but it can be used together with the IPC_CREAT mark to ensure that the obtained object is newly created, rather than opening an existing object.
We recommend that you use 0666 | IPC_CREAT as the shmflg value.
Read and Write Permissions include:

Indicates the read/write permission of the System V shared memory area.

After the System V shared memory area is created, the size of the memory area will be initialized to 0, which is different from the POSIX shared memory, the POSIX standard does not specify the initial content of the newly created POSIX shared memory zone.

Test code:

# Include <stdio. h> # include <stdlib. h> # include <sys/types. h> # include <sys/ipc. h> # include <sys/shm. h> main () {key_t lKey; int nShmId; if (lKey = ftok ("/etc/profile", 1) <0) {perror ("ftok "); exit (1);} if (nShmId = shmget (lKey, 256, IPC_CREAT | 0666) =-1) // create {perror ("shmget "); exit (2);} printf ("Shmid = % d \ n", nShmId); return 0 ;}
Output:
[Root @ MiWiFi-R 1CM csdnblog] #./a. out
Shmid = 0

4. Map the shared memory shmat

After a shared memory area object is created or opened through shmget, the shared memory area is not mapped to the address space of the calling process. Therefore, the shared memory area cannot be accessed. You need to use the shmat function, the shared memory area can be accessed only when it is connected to the address space of the calling process. After the process completes access to the shared memory area, it can call shmdt to disconnect the shared memory area, of course, after the process ends, it will automatically disconnect all connected shared memory zones. The shmat and shmdt functions are described as follows:

// The shmat is used to connect a shared memory area to the address space of the calling process. # Include <sys/shm. h> void * shmat (int shmid, const void * shmaddr, int shmflg); // The start address of the ing area is returned successfully, and-1 is returned if the ing area fails to be returned.

Shmid: The identifier of the opened System V shared memory object, that is, the ID of the shared memory.

Shmaddr is the starting address of the shared memory. The shmaddr and shmflg parameters jointly determine the specific address for connecting the shared memory area to the calling process. The rules are as follows:

· Shmaddr is a null pointer: the connection address is determined by the system kernel. This is a recommended method with portability.

· Shmaddr is not empty: The SHM_RND flag must be specified based on the shmflg parameter:

-- No SHM_RND is specified. The shared memory area is connected to the address specified by the shmaddr of the calling process;

-- Specify SHM_RND: connect the shared memory area to the shmaddr. Specify the address to round down the SHMLBA location.

Shmflg: in addition to the SHM_RND mentioned above, you can also specify the SHM_RDONLY flag to restrict read-only access. If it is SHM_RDONLY, it is read-only mode. The other is the read/write mode. Generally, this flag is set to 0.

# Include <stdio. h> # include <stdlib. h> # include <sys/types. h> # include <sys/ipc. h> # include <sys/shm. h> # include <string. h> typedef struct {int n; char str [256];} ShmStru; main () {key_t lKey; int nShmId; ShmStru * pstru; if (lKey = ftok ("/etc/profile", 2) <0) {perror ("ftok"); exit (1 );} if (nShmId = shmget (lKey, sizeof (ShmStru), IPC_CREAT | 0666) =-1) // create shared memory {perror ("shmget "); exit (2);} if (pstru = shmat (nShmId, NULL, 0) = (void *)-1) // map shared memory to local {perror ("shmat"); exit (3) ;}pstru-> n = 1; // modify shared memory strcpy (pstru-> str, "123456"); // write data to the shared memory if (shmdt (pstru) =-1) // remove the shared memory ing {perror ("shmdt "); exit (4);} return 0 ;}

5. Delete the shared memory ing shmdt

Shmdt is used to disconnect a shared memory area from this process. When a process is terminated, all shared memory areas connected to it are automatically disconnected.

Int shmdt (const void * shmaddr); // success returns 0, Failure Returns-1

Shmaddr is the starting address of the shared memory.

6. Control the shared memory ing shmctrl

The shmctl function can perform various control operations on the shared memory area. The following describes the interface of the shmctl function:

# Include <sys/types. h> # include <sys/ipc. h> # include <sys/shm. h> int shmctl (int shmid, int cmd, struct shmid_ds * buf); // success returns 0, Failure Returns-1

Shmid: the ID of the shared memory, that is, the identifier of the shared memory area.

Cmd: for the command to control operations in the shared memory area, SUS of Open Group defines three operation commands:

· IPC_SET: changes the shared memory status. Set shm_perm.uid, shm_perm.gid, and shm_perm.mode in the operation permission field of the shared memory according to the content specified by the third parameter buf. This command can only be executed by the following processes: a valid user ID is shm_perm.uid or shm_perm.cuid, and a process with super user permissions.

· IPC_STAT: Get the shared memory status. Obtain the shmid_ds structure of the shared memory area and store it in the third parameter passed in.

· IPC_RMID: deletes the shared memory. Delete the shared memory area from the system kernel. Because each shared memory area has a connection data count, unless the last process connecting to the shared memory area is disconnected or terminated, the shared memory area will not be actually deleted. This is very different from the deletion of Other System v ipc, such as the System V message queue, but it is very familiar with the xxx_unlink deletion operation of posix ipc. After this command is called, the shared memory region identifier cannot be connected again. This command can only be executed by the following processes: a valid user ID is equivalent to shm_perm.uid or shm_perm.cuid, and a process with super user permissions.

Buf: a struct pointer. In IPC_STAT, the obtained status is placed in this struct. To change the shared memory status, use this struct.

When using shared memory, after the program exits, if you have not used shmctl () in the program to delete the shared memory, you must use the ipcrm command to delete the shared memory. If you don't care, it's always there.

The following is the test code for creating a System V shared memory zone and viewing its attributes:

#include <iostream>  #include <cstring>  #include <errno.h>  #include <unistd.h>  #include <fcntl.h>  #include <sys/shm.h>  #define PATH_NAME "/tmp/shm"  int main(){        int fd;        if ((fd = open(PATH_NAME, O_CREAT, 0666)) < 0)        {                std::cout << "open file " << PATH_NAME << "failed.";                std::cout << strerror(errno) << std::endl;                return -1;        }        close(fd);        key_t key = ftok(PATH_NAME, 0);        int shmID;        if ((shmID = shmget(key, sizeof(int), IPC_CREAT | 0666)) < 0)        {                std::cout << "shmget failed..." << strerror(errno) << std::endl;                return -1;        }        shmid_ds shmInfo;        shmctl(shmID, IPC_STAT, &shmInfo);        std::cout << "shm key:0x" << std::hex << key << std::dec << key << std::endl;        std::cout << "shm id:" << shmID << std::endl;        std::cout << "shm_segsz:" << shmInfo.shm_segsz << std::endl;        std::cout << "shm_nattch:" << shmInfo.shm_nattch << std::endl;        return 0;}

The execution result is as follows:
[Root @ MiWiFi-R 1CM csdnblog] #./a. out
Shm key: 0x32aa12970
Shm id: 65538
Shm_segsz: 4 // size of the shared memory area
Shm_nattch: 0 // Number of connections in the shared memory area

Run the ipcs command to view the newly created shared memory area object:
[Root @ MiWiFi-R 1CM csdnblog] # ipcs-m-I 65538
Shared memory Segment shmid = 65538
Uid = 0 gid = 0 cuid = 0 cgid = 0
Mode = 0666 access_perms = 0666
Bytes = 4 lpid = 0 cpid = 13414 nattch = 0
Att_time = Not set
Det_time = Not set
Change_time = Mon Jun 22 00:21:34 2015

7. Shared Memory zone restrictions

Like System v ipc, System V shared memory also has System restrictions. For System Restrictions on shared memory, Linux 2.6.18 <bits/shm. h> defines the shminfo structure, which shows the limits of the system kernel, as follows:

# Include <bits/shm. h> struct shminfo {unsigned long int shmmax; // maximum number of bytes in a shared memory area unsigned long int shmmin; // the minimum number of bytes in a shared memory area unsigned long int shmmni; // maximum number of objects in the shared memory area within the system range: unsigned long int shmseg; // The maximum number of shared memory areas connected by each process: unsigned long int shmall; // The maximum number of pages in the shared memory area within the system range: unsigned long int _ unused1; unsigned long int _ unused2; unsigned long int _ unused3; unsigned long int _ unused4 ;};

In Linux, you can specify IPC_INFO in shmctl to obtain the system restrictions shown in the above structure. In Linux, you can view the specific limits through sysctl, as shown below:
[Root @ MiWiFi-R 1CM csdnblog] # sysctl-a | grep shm
Kernel. shmmax = 4294967295 // maximum number of bytes in a shared memory area
Kernel. shmall = 268435456 // maximum number of pages in the shared memory area within the system range
Kernel. shmmni = 4096 // maximum number of objects in the shared memory area within the system range
..............

Generally, you do not need to modify the System restriction process in the System V shared memory zone, because it can basically meet application requirements. If you want to modify the kernel restriction within the System range, in Linux, you can modify/etc/sysctl. conf kernel parameter configuration file, and then use the sysctl command to set kernel parameters. For example:
[Root @ MiWiFi-R 1CM csdnblog] # echo "kernel. shmmni = 1000">/etc/sysctl. conf
[Root @ MiWiFi-R 1CM csdnblog] # sysctl-p
[Root @ MiWiFi-R 1CM csdnblog] # sysctl-a | grep shm
Kernel. shmmni = 1000
Kernel. shmall = 268435456
Kernel. shmmax = 4294967295

8. Use of the shared memory Zone

The following is an example of using the System V shared memory area. Process 1 sends a message to process 2 through the shared memory area, and uses the System V semaphore to synchronize the shared memory area.
The test code is as follows:

// Process 1 # include <iostream> # include <cstring> # include <errno. h> # include <unistd. h> # include <fcntl. h> # include <sys/shm. h> # include <sys/sem. h> using namespace std; # define PATH_NAME "/tmp/shm" union semun {int val; struct semid_ds * buf; unsigned short int * array; struct seminfo * _ buf;}; int main () {int fd; if (fd = open (PATH_NAME, O_RDONLY | O_CREAT, 0666) <0) {cout <"open file" <PATH_NAME <"failed. "; cout <strerror (errno) <endl; return-1;} close (fd); key_t keyShm = ftok (PATH_NAME, 0); key_t keySem = ftok (PATH_NAME, 1); int shmID, semID; if (shmID = shmget (keyShm, sizeof (int), IPC_CREAT | 0666) <0) {cout <"shmget failed. "<strerror (errno) <endl; return-1;} int * buf = (int *) shmat (shmID, 0, 0 ); if (semID = semget (keySem, 1, IPC_CREAT | 0666) <0) {cout <"semget failed. "<strerror (errno) <endl; return-1;} semun arg; arg. val = 0; // The number of initial semaphore resources is 0if (semctl (semID, 0, SETVAL, arg) <0) {cout <"semctl error" <strerror (errno) <endl; return-1;} struct sembuf buffer; buffer. sem_num = 0; buffer. sem_op = 1; buffer. sem_flg = 0; * buf = 12345678; cout <"process 1: send" <* buf <endl; // Add semaphores to 1, to indicate that the existing resources in the shared memory zone are semop (semID, & buffer, 1); return 0;} // process 2 # include <iostream> # include <cstring> # include <errno. h> # include <unistd. h> # include <fcntl. h> # include <sys/shm. h> # include <sys/sem. h> using namespace std; # define PATH_NAME "/tmp/shm" union semun {int val; struct semid_ds * buf; unsigned short int * array; struct seminfo * _ buf;}; int main () {int fd; if (fd = open (PATH_NAME, O_RDONLY) <0) {cout <"open file" <PATH_NAME <"failed. "; cout <strerror (errno) <endl; return-1;} close (fd); key_t keyShm = ftok (PATH_NAME, 0); key_t keySem = ftok (PATH_NAME, 1); int shmID, semID; if (shmID = shmget (keyShm, sizeof (int), 0) <0) {cout <"shmget failed... "<strerror (errno) <endl; return-1;} int * buf = (int *) shmat (shmID, 0, 0 ); if (semID = semget (keySem, 1, 0) <0) {cout <"semget failed... "<strerror (errno) <endl; return-1;} struct sembuf buffer; buffer. sem_num = 0; buffer. sem_op =-1; buffer. sem_flg = 0; // obtain semop (semID, & buffer, 1); cout <"process 2: recv" <* buf <endl; return 0 ;}

Test results:

[Root @ MiWiFi-R 1CM csdnblog] #./test1
Process 1: send 12345678
[Root @ MiWiFi-R 1CM csdnblog] #./test2
Process 2: recv 12345678

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.