Home > System Tutorial > LINUX > Linux IPC System V Shared Memory: An Advanced Approach to High-Speed ​​Data Exchange

Linux IPC System V Shared Memory: An Advanced Approach to High-Speed ​​Data Exchange

WBOY
Release: 2024-02-13 08:30:32
forward
1297 people have browsed it

Linux system is an operating system that supports concurrent execution of multi-tasks. It can run multiple processes at the same time, thereby improving system utilization and efficiency. However, if data exchange and collaboration are required between these processes, some inter-process communication (IPC) methods need to be used, such as signals, message queues, semaphores, etc. Among them, System V shared memory is a relatively advanced and high-speed IPC method that allows two or more processes to exchange data through a memory area without the need for data copying and conversion. This article will introduce the method of System V shared memory in Linux systems, including the creation, mapping, reading, writing, unmapping and deletion of shared memory.

Linux IPC System V 共享内存:一种实现高速数据交换的高级方式

Model

#include
#include
#include
ftok()      //获取key值            
shmget()    //创建/获取共享内存 
shmat()     //挂接共享内存        
shmdt()     //脱接共享内存        
shmctl()    //删除共享内存        
Copy after login

ftok()

//获取key值, key值是System V IPC的标识符,成功返回key,失败返回-1设errno
//同pathname+同 proj_id==>同key_t;
key_t ftok(const char *pathname, int proj_id);
Copy after login

pathname: File name
proj_id: a number from 1 to 255, representing project_id

key_t key=ftok(".",100);    //“.”就是一个存在且可访问的路径, 100是假设的proj_id
    if(-1==key)
        perror("ftok"),exit(-1);
Copy after login

shmget()

//创建/获取共享内存,成功返回共享内存的标识符shmid,失败返回-1设errno
int shmget(key_t key, size_t size, int shmflg);     //多设为int shmid=...  和shmat()一起用比较好看
Copy after login

key: The return value of ftok()
size: The size of the shared memory will actually be allocated according to the page size (PAGE_SIZE). 0 means to obtain the allocated shared memory
shmflg: Specific operation flag

  • IPC_CREAT: If it does not exist, create it. You need to set "|Permission Information" in shmflg, eg: |0664; If it exists, open it
  • IPC_EXCL: Used in conjunction with IPC_CREAT, if it exists, the creation will fail ==> an error will be reported, set errno
  • 0: Get existing shared memory
//创建shared memory
shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0664);
if(-1==shmid)
    perror("shmget"),exit(-1);
Copy after login

Q: Since shmget() can create, what is the use of ftok()
A: shmget is used to create shared memory, ftok() is only used to generate A key. In fact, you can also run it by filling in a number at the key position. However, compared with the system-generated one, it is easy to cause conflicts, so it is best to use ftok to generate a key

shmat()

//挂接共享内存,成功返回映射内存的地址,失败返回(void*)-1设errno
void *shmat(int shmid, const void *shmaddr, int shmflg);
Copy after login

shmid: The return value of shmget()
shmaddr

  • NULL means selected by the system (same as mmap())
  • If it is not NULL and shflg is SHM_RND, it will find the nearest address starting from shmaddr and start allocating points according to the principle of page alignment. Otherwise, the address specified by shmaddr must be page aligned
  • shmflg: The flag of the operation, just give it 0
    • SHM_RDONLYIndicates that the process attached to the shared memory must have read permission
    • SHM_REMAP (Linux-specific) means that if the shared memory to be mapped already has existing memory, then replace the old one
//挂接共享内存
void* pv=shmat(shmid,NULL,0);
if((void*)-1==pv)
    perror("shmat"),exit(-1);
Copy after login

shmdt()

//脱接共享内存,成功返回0,失败返回-1设errno
int shmdt(const void *shmaddr);
//脱接shm
int res=shmdt(pv);
if(-1==res)
    perror("shmdt"),exit(-1);
Copy after login

shmctl()

//共享内存管理,成功返回0,失败返回-1设errno
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Copy after login

shmid: The id of the shared memory, returned by shmget()
buf: Pointer of type shmid_ds

struct shmid_ds {
   struct ipc_perm  shm_perm;       /* Ownership and permissions */
    size_t          shm_segsz;      /* Size of segment (bytes) */
    time_t          shm_atime;      /* Last attach time */
    time_t          shm_dtime;      /* Last detach time */
    time_t          shm_ctime;      /* Last change time */
    pid_t           shm_cpid;       /* PID of creator */
    pid_t           shm_lpid;       /* PID of last shmat(2)/shmdt(2) */
    shmatt_t        shm_nattch;     /* No. of current attaches */
    ...
};
//
struct ipc_perm {
   key_t            __key;      /* Key supplied to shmget(2) */
   uid_t            uid;        /* Effective UID of owner */
   gid_t            gid;        /* Effective GID of owner */
   uid_t            cuid;       /* Effective UID of creator */
   gid_t            cgid;       /* Effective GID of creator */
   unsigned short   mode;       /* Permissions + SHM_DEST and SHM_LOCKED flags */
   unsigned short   __seq;      /* Sequence number */
};
Copy after login

cmd

  • IPC_STAT表示从内核中拷贝关于这个shmid的信息到buf指向的shmid_ds中

  • IPC_SET 将buf指向的shmid_ds的信息写入到内核的结构体中,同时更新成员shm_ctime

  • IPC_RMID销毁共享内存

  • IPC_INFO(Linux-specific)返回系统对共享内存的限制写入到buf指向的时shminfo结构体中

    //_GNU_SOURCE
    struct  shminfo {
        unsigned long   shmmax; /* Maximum segment size */
        unsigned long   shmmin; /* Minimum segment size; always 1 */
        unsigned long   shmmni; /* Maximum number of segments */
        unsigned long   shmseg; /* Maximum number of segments that a process 
    can attach; unused within kernel */
        unsigned long   shmall; /* Maximum number of pages of shared memory, 
    system-wide */
     };
     //shmmni, shmmax, and shmall 可以童工/proc里的同名文件进行修改
    
    Copy after login
  • SHM_INFO(Linux-specific) 返回一个shm_info结构体来表示该共享内存消耗的系统资源

    //_GNU_SOURCE
    struct shm_info {
        int             used_ids;   /* # of currently existing segments */
        unsigned long   shm_tot;    /* Total number of shared memory pages */
        unsigned long   shm_rss;    /* # of resident shared memory pages */
        unsigned long   shm_swp;    /* # of swapped shared memory pages */
        unsigned long   swap_attempts; /* Unused since Linux 2.4 */
        unsigned long   swap_successes;/* Unused since Linux 2.4 */
     };
    
    Copy after login
  • SHM_STAT(Linux-specific) 为IPC_STAT返回一个shmid_ds结构结构体,不同的是shmid的参数不是一个标识符,而是内核中一个包含了系统中所有共享内存信息的索引

  • SHM_LOCK防止系统将共享内存放到swap区,IPC_STAT读到的信息中SHM_LOCKED标记就被设置了

  • SHM_UNLOCK 解除锁定,即允许共享内存被系统放到swap区

//使用IPC_RMID删除共享内存
int res=shmctl(shmid,IPC_RMID,NULL);
if(-1==res)
    perror("shmctl"),exit(-1);
Copy after login

例子

//Sys V IPC shm
int shmid;          //定义全局变量记录id
void fa(int signo){
    printf("deleting shared memories...\n");
    sleep(3);//其实没用
    int res=shmctl(shmid,IPC_RMID,NULL);
    if(-1==res)
        perror("shmctl"),exit(-1);
    printf("delete success\n");
    exit(0);    //ctrl+C已经不能结束while(1),用exit(0)来终结
}
int main(){
    //获取key
    key_t key=ftok(".",100);    //.就是一个存在且可访问的路径, 100是随便给的
    if(-1==key)
        perror("ftok"),exit(-1);
    printf("key=%#x\n",key);    //打印出进制的标示,即0x
    //创建shared memory
    shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0664);
    if(-1==shmid)
        perror("shmget"),exit(-1);
    printf("shmid=%d\n",shmid);
    //挂接shm
    void* pv=shmat(shmid,NULL,0);
    if((void*)-1==pv)
        perror("shmat"),exit(-1);
    printf("link shared memory success\n");
    //访问shm
    int* pi=(int*)pv;
    *pi=100;
    //脱接shm
    int res=shmdt(pv);
    if(-1==res)
        perror("shmdt"),exit(-1);
    printf("unlink success\n");
    //如果不再使用,删除shm
    printf("删除共享内存请按Ctrl C...\n");
    if(SIG_ERR==signal(SIGINT,fa))
        perror("signal"),exit(-1);
    while(1);
    return 0;
}
Copy after login

本文介绍了Linux系统中System V 共享内存的方法,包括共享内存的创建、映射、读写、解除映射和删除等方面。通过了解和掌握这些知识,我们可以更好地使用System V 共享内存来实现进程间通信,提高系统的性能和可靠性。当然,Linux系统中System V 共享内存还有很多其他的特性和用法,需要我们不断地学习和探索。希望本文能给你带来一些启发和帮助。

The above is the detailed content of Linux IPC System V Shared Memory: An Advanced Approach to High-Speed ​​Data Exchange. For more information, please follow other related articles on the PHP Chinese website!

source:lxlinux.net
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template