找回密码
 立即注册
软件设计/软件工程 2022-05-02 260 0star收藏 版权: . 保留作者信息 . 禁止商业使用 . 禁止修改作品
共享内存
共享内存是系统为多个进程之间的通信保留的一块内存区域。 在/proc/sys/kernel/目录下记录了共享内存的一些限制,比如共享内存区域的最大字节数shmmax、系统中共享内存区域标识的最大数量shmmni等,其中 可以手动调整。 但这不推荐。

应用
共享内存的使用主要包括以下API:ftok()、shmget()、shmat()、shmdt()和shmctl()。

ftok()
使用 ftok() 函数获取 ID 号。

应用说明:

在 IPC 中,我们经常使用 key_t 的值来创建或打开信号量、共享内存和消息队列。

函数原型:

key_t ftok(const char *pathname, int proj_id);
键:

路径名必须存在于系统中并且可由进程访问
proj_id 是 1-255 之间的整数值,典型值是 ASCII 值。
执行成功时会返回一个key_t值,否则返回-1。 我们可以使用 strerror(errno) 来确定具体的错误信息。

考虑到应用系统可能应用在不同的主机上,可以直接定义一个key,而不是通过ftok获取:

#define IPCKEY 0x344378
shmget()
shmget() 是一个用于打开/指向共享内存的函数

应用说明:
shmget() 用于获取共享内存区域的ID,如果指定的共享区域不存在,则创建对应的区域。

函数原型:
int shmget(key_t key, size_t size, int shmflg);
  key_t key 是这块共享内存的标识符。

在父子关系中的进程间通信的情况下,这个标识符被替换为 IPC_PRIVATE。

如果两个进程之间没有关系,使用 FTOK() 计算一个标识符(或自己定义一个)并使用它。

int size 是这个内存的大小。
int flag 是该内存的模式和权限标志。



该模式可以采用以下值:

IPC_CREAT 新建(如果已经创建,则返回当前共享内存的id)
IPC_EXCL 与 IPC_CREAT 结合使用,如果已创建则返回错误
那么“mode”和“authority ID”就是“or”作为第三个参数。
例如:IPC_CREAT | IPC_EXCL | 0640

例子中0666是权限标识,4/2/1分别代表读/写/执行3个权限,第一个0是UID,第一个6(4+2)代表所有者的权限,第二个4表示同组的权限,第三个0代表其他人的权限。
此函数在成功时返回共享内存的 ID,在失败时返回 -1。



  防范措施:

创建共享内存时,shmflg 参数至少需要 IPC_CREAT | IPC_EXCL 权限标识符。如果只有IPC_CREAT,则申请地址为k=0xffffffff,不能使用;
shmflg在获取创建的共享内存时,不要使用IPC_CREAT(只有创建共享内存时的权限标志,如0640),否则在某些情况下,如用ipcrm删除共享内存后,使用该函数并使用IPC_CREAT参数获取 一旦共享内存被获取(当然获取失败),即使重新创建共享内存也不会成功。此时,必须更改密钥以重建共享内存。



shmat()


shmat() 将此内存区域映射到进程的虚拟地址空间。

函数原型:
void    *shmat( int shmid , char *shmaddr , int shmflag );
shmat() 是一个函数,用于允许该进程访问一块共享内存。

int shmid 是该共享内存的 ID。
char *shmaddr 是共享内存的起始地址。 如果 shmaddr 为 0,内核会将共享内存映射到调用进程地址空间中选定的位置; 如果 shmaddr 不为 0,内核会将共享内存映射到 shmaddr 指定的位置。 所以一般设置 shmaddr 为 0。
int shmflag 是该进程对该内存的操作模式。 如果为 SHM_RDONLY,则为只读模式。 其他是读写模式
成功时,此函数返回共享内存的起始地址。 失败时返回 -1。


   shmdt()


   shmdt() 函数删除进程对该内存的使用。 与 shmat() 相比,shmdt() 是一个用于禁止进程访问一块共享内存的函数。

函数原型:
int shmdt( char *shmaddr );


  参数char *shmaddr是那块共享内存的起始地址。
  成功时返回0。失败时返回-1。



shmctl()


  shmctl() 控制对这块共享内存的使用

  函数原型:

int shmctl( int shmid , int cmd , struct shmid_ds *buf );


  int shmid是共享内存的ID。
  int cmd是控制命令,可取值如下:

  IPC_STAT        得到共享内存的状态
  IPC_SET         改变共享内存的状态
  IPC_RMID        删除共享内存


  struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
  返回值:   成功:0
                失败:-1



共享内存示例

1 #include <sys/ipc.h>
2 #include <sys/shm.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #define IPCKEY 0x366378
8
9 typedef struct
10 {
11     char agen[10];
12     unsigned char file_no;
13 } st_setting;
14
15 int main(int argc, char** argv)
16 {
17     int shm_id;
18     key_t key;
19     st_setting *p_setting;
20
21     //首先检查共享内存是否存在,存在则先删除
22     shm_id = shmget(IPCKEY ,1028,0640); //得到共享内存,内存大小,权限位
23     if(shm_id != -1)//共享内存存在
24     {
25         p_setting = (st_setting*)shmat(shm_id,NULL,0);//映射共享内存,自动完成映射
26         if ( p_setting != (void *)-1)
27         {
28             shmdt(p_setting);
29             shmctl(shm_id,IPC_RMID,0) ;
30         }
31     }
32
33     shm_id=shmget(IPCKEY,1028,0640|IPC_CREAT|IPC_EXCL);
34     if(shm_id==-1)
35     {
36         printf("shmget error\n");
37         return -1;
38     }
39     //将这块共享内存区附加到自己的内存段
40     p_setting=(st_setting*)shmat(shm_id,NULL,0);
41
42     strncpy(p_setting->agen,"成鹏",10);
43     printf( "agen:%s\n",p_setting->agen );
44
45     p_setting->file_no = 1;
46     printf( "file_no:%d\n",p_setting->file_no );
47
48     system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为1
49
50     //将这块共享内存区从自己的内存段删除出去
51     if(shmdt(p_setting) == -1)
52         perror(" detach error ");
53
54     system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为0
55
56     //删除共享内存
57     if (shmctl( shm_id , IPC_RMID , NULL ) == -1)
58         perror(" delete error ");
59
60     //exit(0);
61
62 }
View Code
  

注意事项


  在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。



ipcs命令和ipcrm命令


取得ipc信息:
ipcs [-m|-q|-s]
-m     输出有关共享内存(shared memory)的信息
-q      输出有关信息队列(message queue)的信息
-s      输出有关“遮断器”(semaphore)的信息
%ipcs -m



删除ipc
ipcrm -m|-q|-s shm_id
%ipcrm -m 105



ftok陷阱


  采用ftok来生成key的情况下,如果ftok的参数pathname指定文件被删除后重建,则文件系统会赋予这个同名文件(或目录)新的i节点信息,于是这些进程所调用的ftok虽然都能正常返回,但得到的键值却并不能保证相同。

(Shared memory
Shared memory is an area of memory reserved by the system for communication between multiple processes. Some limitations of shared memory are recorded in the / proc / sys / kernel / directory, such as the maximum number of bytes of shared memory area SHMMAX and the maximum number of shared memory area identifiers SHMMNI in the system, which can be adjusted manually. But this is not recommended.
application
The usage of shared memory mainly includes the following APIs: ftok (), shmget (), shmat (), shmdt (), and shmctl ().
ftok()
Use the ftok() function to get the ID number.
Application Description:
In IPC, we often use key_ T to create or open semaphores, shared memory, and message queues.
Function prototype:
key_ t ftok(const char *pathname, int proj_id);
Key:
The pathname must exist in the system and be accessible by the process
proj_ ID is an integer value between 1 and 255, typically ASCII.
A key will be returned when the execution is successful_ T value, otherwise - 1 is returned. We can use strError (errno) to determine the specific error information.
Considering that the application system may be applied on different hosts, you can directly define a key instead of obtaining it through ftok:
#define IPCKEY 0x344378
shmget()
Shmget () is a function to open / point to shared memory
Application Description:
Shmget() is used to obtain the ID of the shared memory area. If the specified shared area does not exist, the corresponding area will be created.
Function prototype:
int shmget(key_t key, size_t size, int shmflg);
key_ T key is the identifier of this shared memory.
In the case of interprocess communication in a parent-child relationship, this identifier is replaced by IPC_ PRIVATE。
If there is no relationship between the two processes, use ftok () to calculate an identifier (or define one yourself) and use it.
Int size is the size of this memory.
Int flag is the mode and permission flag of the memory.
This mode can take the following values:
IPC_ Create new (if it has been created, return the ID of the current shared memory)
IPC_ Excl and IPC_ Used in combination with creat. If it has been created, an error is returned
Then "mode" and "authority ID" are "or" as the third parameter.
For example: IPC_ CREAT | IPC_ EXCL | 0640
In the example, 0666 is the permission ID, 4 / 2 / 1 represents read / write / execute three permissions respectively, the first 0 is uid, the first 6 (4 + 2) represents the permission of the owner, the second 4 represents the permission of the same group, and the third 0 represents the permission of others.
This function returns the ID of the shared memory on success and - 1 on failure.
Precautions:
When creating shared memory, the shmflg parameter requires at least IPC_ CREAT | IPC_ Excl permission identifier. If only IPC_ Creat, then the application address is k = 0xFFFFFFFF and cannot be used;
Shmflg do not use IPC when getting the created shared memory_ Creat (only the permission flag when creating shared memory, such as 0640). Otherwise, in some cases, such as deleting shared memory with ipcrm, use this function and use IPC_ Create parameter acquisition once the shared memory is acquired (of course, the acquisition fails), even if the shared memory is recreated, it will not succeed. At this point, you must change the key to rebuild shared memory.
shmat()
Shmat () maps this memory area to the virtual address space of the process.
Function prototype:
void    *shmat( int shmid , char *shmaddr , int shmflag );
Shmat () is a function that allows the process to access a piece of shared memory.
Int shmid is the ID of the shared memory.
Char * shmaddr is the starting address of shared memory. If shmaddr is 0, the kernel will map the shared memory to the selected location in the address space of the calling process; If shmaddr is not 0, the kernel maps the shared memory to the location specified by shmaddr. Therefore, shmaddr is generally set to 0.
Int shmflag is the operation mode of the process on the memory. If SHM_ Rdonly, read-only mode. The other is read-write mode
On success, this function returns the starting address of the shared memory. Returns - 1 on failure.
shmdt()
The shmdt() function deletes the memory used by the process. In contrast to shmat (), shmdt () is a function that prevents a process from accessing a piece of shared memory.
Function prototype:
int shmdt( char *shmaddr );
The parameter char * shmaddr is the starting address of the shared memory.
Returns 0 on success. Returns - 1 on failure.
shmctl()
Shmctl () controls the use of this shared memory
Function prototype:
int shmctl( int shmid , int cmd , struct shmid_ds *buf );
Int shmid is the ID of the shared memory.
Int CMD is a control command with the following values:
IPC_ Stat gets the status of shared memory
IPC_ Set changes the state of shared memory
IPC_ Rmid delete shared memory
struct shmid_ Buds is a pointer structure. IPC_ During stat, the obtained state is placed in this structure. If you want to change the state of shared memory, use this structure to specify.
Return value: Success: 0
Failed: - 1
Shared memory example
1 #include <sys/ipc. h>
2 #include <sys/shm. h>
3 #include <string. h>
4 #include <stdio. h>
5 #include <stdlib. h>
six
7 #define IPCKEY 0x366378
eight
9 typedef struct
10 {
11     char agen[10];
12     unsigned char file_ no;
13 } st_ setting;
fourteen
15 int main(int argc, char** argv)
16 {
17     int shm_ id;
18     key_ t key;
19     st_ setting *p_ setting;
twenty
21 / / first check whether the shared memory exists. If so, delete it first
22     shm_ id = shmget(IPCKEY ,1028,0640); // Get the shared memory, memory size and permission bits
23 if (shm_id! = - 1) / / shared memory exists
24     {
25         p_ setting = (st_setting*)shmat(shm_id,NULL,0);// Mapping shared memory, automatic mapping
26         if ( p_setting != (void *)-1)
27         {
28             shmdt(p_setting);
29             shmctl(shm_id,IPC_RMID,0) ;
30         }
31     }
thirty-two
33     shm_ id=shmget(IPCKEY,1028,0640|IPC_CREAT|IPC_EXCL);
34     if(shm_id==-1)
35     {
36         printf("shmget error\n");
37         return -1;
38     }
39 / / attach this shared memory area to its own memory segment
40     p_ setting=(st_setting*)shmat(shm_id,NULL,0);
forty-one
42 strncpy (p_setting - > agen, "Cheng Peng", 10);
43     printf( "agen:%s\n",p_setting->agen );
forty-four
45     p_ setting->file_ no = 1;
46     printf( "file_no:%d\n",p_setting->file_no );
forty-seven
48     system("ipcs -m");// At this time, you can see the information that a process is associated with the shared memory. Nattch is 1
forty-nine
50 / / delete this shared memory area from its own memory segment
51     if(shmdt(p_setting) == -1)
52         perror(" detach error ");
fifty-three
54     system("ipcs -m");// At this time, you can see the information that a process is associated with the shared memory. Nattch is 0
fifty-five
56 / / delete shared memory
57     if (shmctl( shm_id , IPC_RMID , NULL ) == -1)
58         perror(" delete error ");
fifty-nine
60     //exit(0);
sixty-one
62 }
View Code
matters needing attention
When using shared memory, after the program exits. If you don't use shmctl () to delete the shared memory in the program, be sure to delete the shared memory with ipcrm command on the command line. If you don't care, it'll always be there.
IPCs command and ipcrm command
Obtain IPC information:
ipcs [-m|-q|-s]
-M outputs information about shared memory
-Q outputs information about the message queue
-S outputs information about the semaphore
%ipcs -m
Delete IPC
ipcrm -m|-q|-s shm_ id
%ipcrm -m 105
Ftok trap
When ftok is used to generate the key, if the file specified by the parameter pathname of ftok is deleted and rebuilt, the file system will give the file (or directory) with the same name new i-node information. Therefore, although the ftok called by these processes can return normally, the key values obtained cannot be guaranteed to be the same.
)





上一篇:IOS 开发的窗口和视图
下一篇:DELPHI2009下编译提示“找不到”EXCEL_TLB”