Unix/linux shared memory applications and traps

Source: Internet
Author: User
Tags function prototype goto message queue

Unix/linux shared memory applications and traps (2012-06-12-14:32)
Tags: Linux memory classification: Linux applications

Shared memory is a piece of memory that is reserved for the system to be considered for communication between multiple processes. In the/proc/sys/kernel/directory, some limitations of shared memory are recorded, such as the maximum number of bytes in a shared memory area Shmmax, the maximum number of system-wide shared memory area identifiers Shmmni, etc., which can be adjusted manually, but not recommended.
First, the application
The use of shared memory mainly includes the following Api:ftok (), Shmget (), Shmat (), SHMDT (), and Shmctl ().
1) Use the Ftok () function to obtain an ID number.
Application notes:
In IPC, we often use the value of key_t to create or open semaphores, shared memory, and Message Queuing.
Function Prototypes:
key_t Ftok (const char *pathname, int proj_id);
Keys:
1) pathname must be present in the system and the process can access the
3) proj_id is an integer value between 1-255 and a typical value is an ASCII value.
When executed successfully, a key_t value is returned, otherwise-1 is returned. We can use Strerror (errno) to determine the specific error message.
Given that the application may be applied on a different host, you can define a key directly without ftok getting:
#define Ipckey 0x344378
2) Shmget () function to open/point to a piece of shared memory
Application notes:
Shmget () is used to obtain the ID of the shared memory area, and if the specified shared area does not exist, the corresponding zone is created.
Function Prototypes:
int Shmget (key_t key, size_t size, int shmflg);
key_t key is the identifier for this shared memory. In the case of inter-process communication between parent and child relationships, this identifier is replaced with Ipc_private. If two processes have no relationship, use Ftok () to figure out an identifier (or define it yourself).
int size is the size of this memory.
The INT flag is the pattern (mode) of this memory and the identity of the permission.
The pattern is preferable to the following values:
Ipc_creat new (returns the ID of the current shared memory if created)
IPC_EXCL is used in conjunction with Ipc_creat and returns an error if created
The "mode" and "Permission ID" are then performed "or" as a third parameter.
Example: Ipc_creat | Ipc_excl | 0640
In the example, 0666 is the permission identifier, the 4/2/1 represents the read/write/execute 3 permissions respectively, the first 0 is the UID, the first 6 (4+2) represents the owner's permissions, the second 4 represents the same group permissions, and the 3rd 0 represents the rights of others.
This function returns the ID of the shared memory when it succeeds, and returns 1 on failure.
There are two more sentences to be said about this function.
When creating shared memory, the SHMFLG parameter requires at least Ipc_creat | Permission identification, if only ipc_creat the address of the application is K=0XFFFFFFFF, can not be used;
When you get the shared memory that has been created, shmflg do not use Ipc_creat (which can only be used when creating shared memory, such as 0640), or in some cases, such as using IPCRM to delete shared memory, use the function with the ipc_creat parameter to get the shared memory (of course, Failed), you must change the key to rebuild the shared memory even if the shared memory is not successfully created again.
3) Shmat () maps this memory area to the virtual address space of the process.
Function Prototypes:
void *shmat (int shmid, char *shmaddr, int shmflag);
Shmat () is a function that allows this process to access a piece of shared memory.
int Shmid is the ID of that shared memory.
Char *shmaddr is the starting address for shared memory, and if SHMADDR is 0, the kernel will image the shared memory to the selected location in the calling process's address space, and if SHMADDR is not 0, the kernel will image the shared memory to the location specified by SHMADDR. So the shmaddr is generally set to 0.
int Shmflag is the operating mode of this process for this memory. If it is shm_rdonly, it is read-only mode. The other is the read and write mode
Upon success, this function returns the starting address of the shared memory. Returns-1 on failure.
4) The SHMDT () function removes the use of this memory by the process, SHMDT () and Shmat (), which is used to prohibit the process from accessing a block of shared memory.
Function Prototypes:
int Shmdt (char *shmaddr);
The parameter char *shmaddr is the starting address for that shared memory.
Returns 0 upon success. Returns-1 on failure.
5) Shmctl () controls the use of this shared memory
Function Prototypes:
int shmctl (int shmid, int cmd, struct shmid_ds *buf);
The int shmid is the ID of the shared memory.
int cmd is a control command, and the following values are desirable:
Ipc_stat get the state of shared memory
Ipc_set changing the state of shared memory
Ipc_rmid Deleting shared memory
struct Shmid_ds *buf is a struct-body pointer. When Ipc_stat, the acquired state is placed in the structure. If you want to change the state of shared memory, specify it with this struct.
Return value: Success: 0
Failed:-1
Sample program:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define Ipckey 0x366378
typedef struct{
Char agen[10];
unsigned char file_no;
} st_setting;
int main (int argc, char** argv)
{
int shm_id;
key_t key;
St_setting *p_setting;

First check that the shared memory exists and that it is deleted first
shm_id = Shmget (Ipckey, 1028,0640);
if (shm_id! =-1)
{
p_setting = (st_setting*) shmat (shm_id,null,0);
if (p_setting! = (void *)-1)
{
SHMDT (p_setting);
Shmctl (shm_id,ipc_rmid,0);
}
}

Shm_id=shmget (ipckey,1028,0640| Ipc_creat| IPC_EXCL);
if (shm_id==-1)
{
printf ("Shmget error\n");
return-1;
}
Attach this shared memory area to your own memory segment
P_setting= (st_setting*) Shmat (shm_id,null,0);

strncpy (P_setting->agen, "Jinyh", 10);
printf ("agen:%s\n", P_setting->agen);

P_setting->file_no = 1;
printf ("file_no:%d\n", p_setting->file_no);

System ("ipcs-m");//You can see that there is information about the process associated to the shared memory, Nattch is 1

Remove this shared memory area from your own memory segment
if (SHMDT (p_setting) = =-1)
Perror ("Detach error");

System ("ipcs-m");//You can see that there is information about the process associated to the shared memory, Nattch is 0

Delete Shared memory
if (Shmctl (shm_id, Ipc_rmid, NULL) = =-1)
Perror ("delete error");

Exit (0);

}
Note: After you use shared memory, the end program exits. If you are not using Shmctl () to remove shared memory in the program, be sure to remove the shared memory with the IPCRM command at the command line. If you don't care, it's always there.
Explain briefly the IPCS command and the IPCRM command.
Obtain IPC information:
IPCS [-m|-q|-s]
-m output information about shared memory
-Q Output Information about information queues (message queue)
-S output information about the "breaker" (semaphore)
%ipcs-m
Remove IPC
Ipcrm-m|-q|-s shm_id
%IPCRM-M 105
Second, traps (refer to http://www.ibm.com/developerworks/cn/aix/library/au-cn-sharemem/)
1) Ftok Traps
In the case of Ftok to generate key, if the Ftok parameter pathname the specified file is deleted and rebuilt, then the file system will give the file (or directory) of the same name the new I node information, so the ftok of these processes can return normally, but the resulting key value is not guaranteed to be the same.
2) 3. Shmat Issues in Aix
In Aix systems, System V has limitations in the use of various inter-process communication mechanisms. Unlike other Unix operating systems, where the IPC mechanism is configured differently, AIX uses a different approach, and the upper limit of the IPC mechanism is defined in Aix and is not configurable. As far as the shared memory mechanism is concerned, the following limitations exist on AIX systems in 4.2.1 and later:
For 64-bit processes, a maximum of 268,435,456 shared memory segments can be connected to the same process;
For 32-bit processes, the same process can connect up to 11 shared memory segments, unless the extended Shmat is used;
The above limitations are not cumbersome for 64-bit applications, because the number of connections available is large enough, but for 32-bit applications, it is easy to have unexpected problems because the maximum number of connections is only 11.
The following routine test02.c demonstrates this problem, in order to streamline the code, it repeatedly connects to the same shared memory object, in fact, regardless of whether the connected shared memory object is the same, the limit is the number of connections:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define MAX_ATTACH_NUM 15
void Main (int argc, char* argv[])
{
key_t Mem_key;
Long mem_id;
void* Mem_addr[max_attach_num];
int i;
if (Mem_key = Ftok ("/tmp/mykeyfile", 1)) = = (key_t) (-1)) {
printf ("Failed to generate shared memory access key, errno=%d\n",
errno);
Goto Mod_exit;
}
if (mem_id = Shmget (Mem_key, ipc_creat) = = = (-1)) {
printf ("Failed to obtain shared memory ID, errno=%d\n", ERRNO);
Goto Mod_exit;
}
for (I=1; i<=max_attach_num; i++) {
if ((mem_addr[i] = (void *) Shmat (mem_id, 0, 0) = = (void *) (-1))
printf ("Failed to attach shared memory, times [%02d], errno:%d\n", I,
errno);
Else
printf ("Successfully attached shared memory, times [%02d]\n", I);
}
Mod_exit:
Shmctl (mem_id, Ipc_rmid, NULL);
}
On the AIX system, we compile it as test02 and run it and see the following output:
Successfully attached shared memory, times [01]
Successfully attached shared memory, times [02]
Successfully attached shared memory, times [03]
Successfully attached shared memory, times [04]
Successfully attached shared memory, times [05]
Successfully attached shared memory, times [06]
Successfully attached shared memory, times [07]
Successfully attached shared memory, times [08]
Successfully attached shared memory, times [09]
Successfully attached shared memory, times [10]
Successfully attached shared memory, times [11]
Failed to attach shared memory, times [a], errno:24
Failed to attach shared memory, times [], errno:24
Failed to attach shared memory, times [], errno:24
Failed to attach shared memory, times [], errno:24
After 11 connections are exceeded, all subsequent shared memory connections will not be established. The definition of error code 24 is that the explanation given by Emfile,aix is:
The number of the shared memory segments attached to the calling process exceeds the system-imposed limit.
The solution to this problem is to use the extended Shmat, specifically, before running the relevant application (specifically before the shared memory is created), first setting the EXTSHM environment variable in the shell, extending the shmat through it, without any modification to the source code itself:
Export Extshm=on
It is worth noting that although setting environment variables, in the program can also be done through the SETENV function, such as at the beginning of the program, add the following code:
Setenv ("Extshm", "on", 1);
But the practice proves that such a method is ineffective in solving this problem, that is to say, the only way to do this is to set the EXTSHM environment variable in the shell, not in the program.
When configuring a 32-bit DB2 instance on AIX, it is also required to make sure that the environment variable EXTSHM is set to on, which is required before running Warehouse Manager and Query patroller:
Export Extshm=on
Db2set DB2ENVLIST=EXTSHM
Db2start
The reason for this is that the maximum number of connections is limited when the 32-bit application connects shared memory in the AIX we just introduced. This problem is also prevalent in software products such as Oracle on the AIX platform.
3) issues with Shmget and Shmat in HP-UX
3.1 32-bit and 64-bit application compatibility issues
On the HP-UX platform, if you run 32-bit apps and 64-bit apps at the same time, and they access an identical shared memory area, you encounter compatibility issues.
In HP-UX, the application Settings ipc_creat flag calls Shmget, the shared memory area that is created, can only be accessed by the same type of application, i.e. the shared memory area created by a 32-bit application can only be accessed by other 32-bit applications, as well The shared memory area created by a 64-bit application can only be accessed by other 64-bit applications.
If a 32-bit application attempts to access a shared memory area created by a 64-bit app, it fails when calling Shmget and gets the EINVAL error code, which is interpreted as:
A shared memory identifier exists for key not in 64-bit address space and the process performing the request have been C Ompiled as a 32-bit executable.
The solution to this problem is to combine the IPC_CREAT flag with a given IPC_SHARE32 flag when 64-bit apps create shared memory:
Shmget (Mem_key, size, 0666 | Ipc_creat | IPC_SHARE32)
For 32-bit applications, there is no requirement to set the IPC_SHARE32 flag, but setting this flag does not pose any problem, meaning that the same code can be used regardless of whether the application will be compiled into a 32-bit or 64-bit mode and thus address compatibility issues with shared memory access for 32-bit apps and 64-bit apps.
3.2 Number of connections to the same shared memory limit
On HP-UX, the application process is limited to a maximum of 1 connections to the same shared memory area, unlike the limit on the number of connections on Aix described in section 3rd above, and HP-UX does not set an upper limit on the number of connections to different shared memory areas, which means that An application process running on HP-UX can connect many different shared memory areas at the same time, but only 1 connections are allowed for the same shared memory area, otherwise the Shmat call will fail with the error code EINVAL, which has the following explanation for the error code in Shmat's man help:
Shmid is not a valid shared memory identifier, (possibly because the shared memory segment was already removed using SHMCT L (2) with Ipc_rmid), or the calling process was already attached to Shmid.
This limitation poses an unavoidable problem for multithreaded applications, and will fail if more than 1 threads in an application process attempt to connect to the same shared memory area.
To solve this problem, the application design needs to be modified so that the application process can have multi-threaded access to the same shared memory. The method of solving this problem is more complicated than the solution to the above problem.
As one of the methods to be consulted, the following logic can be a good solution to this problem:
The basic idea is that for each shared memory area, after the application process first connects, it saves its key value (the return value of Ftok), the system identifier (the return value of the Shmid,shmget call), and the access address (that is, the return value of the Shmat call). Leave a record in the form of a global array or list of the processes. Before any connection operation to the shared memory, the program will retrieve the list of records, match the shared memory that you want to access based on the key values and flags, and if a matching record is found, read the access address directly from the record without having to call the Shmat function again to resolve the problem, and if no matching target is found, Call Shmat to establish a connection and add a new record for the shared memory on the new connection.
The data structure of the record entry can be defined in the following form:
typedef struct _SHARED_MEMORY_RECORD
{
key_t Mem_key; Key generated by Ftok ()
int mem_id; ID returned by Shmget ()
void* mem_addr; Access address returned by Shmat ()
int Nattach; Times of attachment
} shared_
4) SHMDT function prototype problem in Solaris
The SHMDT call in the Solaris system differs from the System V standard on the prototype,
Default
int Shmdt (char *shmaddr);
The data type of the formal parameter shmaddr is char * on Solaris, and System V defines the void * type; in fact, the function prototype specification followed by the SHMDT call on Solaris is the standard before svid-v4; for Linux systems, for example, LIBC4 and Libc5 Use char * type parameters, and GLIBC2 and later versions that follow SVID-V4 and subsequent standards are replaced by void * type parameters.
If you still have a standard prototype of System V in your code, you will compile the code on the Solaris, resulting in a compilation error, such as:
Error:formal argument 1 of type char* in call to SHMDT (char*)
is being passed void*.
The workaround is to introduce a conditional compilation macro that takes a char * type parameter when the build platform is Solaris, and still uses the System V standard void * Type parameter for other platforms, such as:
#ifdef _solaris_shared_memory
SHMDT ((char *) mem_addr);
#else
SHMDT ((void *) mem_addr);
#endif
5) Risk of deleting shared memory through SHMCTL
If the shared memory has been disconnected from all the processes that accessed it, the IPC_RMID subcommand is immediately removed, and the shared memory identifier is removed and the shared memory area is deleted, along with any associated data structures;
If there is still another process remaining connected to the shared memory, after calling the IPC_RMID subcommand, the shared memory is not immediately removed from the system, but is set to the Ipc_private state and marked as "deleted", until all existing connections have been disconnected. The shared memory will eventually disappear from the system.
It should be stated that once the shared memory has been deleted through SHMCTL, the shared memory will no longer accept any new connections, even if it still exists in the system! Therefore, it is possible to know that it is not possible to have a new connection after the deletion of the shared memory, it is safe to perform the delete operation, otherwise the connection will fail if a new connection still occurs after the delete operation!

Unix/linux shared memory applications and traps

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.