[Linux] Inter-process communication--System V shared memory

foreword

This blog introduces the second way of inter-process communication – System V
System V has three ways:
共享内存
消息队列
信号量
this blog对于系统调用的函数,会进行一定的封装

insert image description here

1. System V shared memory

2. The principle of shared memory

Processes are independent, and different processes cannot directly obtain each other's data. All communication requires 第三方some intervention, and the pipeline 文件provides shared files in the form of a method.
Anonymous pipes are based on 子进程继承父进程的进程信息the feature that the anonymous pipe created by the parent process can be obtained 文件描述符, which is only applicable to the owning “亲戚关系”process;
the essence of the named pipe is the same as that of the anonymous pipe, but it is created in the current directory 管道文件, and different processes can 不同方式open this pipe file , proceed 读写, 适用于任何不同进程
both pipelines are 内存级文件,不会进行刷盘

So how does System V shared memory enable different processes to communicate?

The premise of inter-process communication is: 让不同进程看到同一份“资源”
pipes pass through files, and System V通过内存实现
insert image description here
System V创建的共享内存通过页表映射放到不同进程的共享区

3. The creation of shared memory

The function to create shared memory is shmget()shared memory get
insert image description here

  1. The first parameter will be explained in detail later
  2. The second parameter is the size of the shared memory created
  3. The third parameter is one 位图, and there are three types of parameters that can be passed:
    (1) IPC_CREAT: If there is no shared memory, create it; if there is, return the shmid of the shared memory
    (2) IPC_CREAT | IPC_EXCL: If there is no shared memory, create it; Return -1 and set the error code. Its role is to ensure that the created shared memory is up to date
    (3) 以上两种 | 权限
    Note: IPC_EXCL不能单独使用, has no effect

The return value is the shared memory created 共享内存的标识符(different from the file descriptor)

Let's explain the first parameter in detail

The shared memory we created 需要不同进程双方都能找到, and when creating a new shared memory 不和其他共享内存冲突, all needs 由系统生成一个key值, try to avoid conflicts and ensure communication between different processes

The function of generating the key value is: ftok()
insert image description here
there may be multiple shared memories in the memory at the same time, and the operating system will also have corresponding structures for them to manage them. This is also a manifestation of describing first and then organizing ideas.
So we need to ensure that different processes can find the same shared memory

The first parameter: path string; the second parameter:
the two parameters of the project ID ftok, 创建后会保存在共享内存结构体的属性中so that the operating system can help us find the shared memory we want to use.
The processes that need to communicate 确保这两个参数传的一样need to find the same shared memory.
The specific content is actually not important ( pathname需要是能找到的文件路径), just make sure that the process to communicate is the same

function to get key value

#define PATHNAME "." 
#define PROJID 0x6666

//获取key值
key_t getKey()
{
    
    
    key_t k=ftok(PATHNAME,PROJID);
    if(k==-1)
    {
    
    
        cerr<<errno<<":"<<strerror(errno)<<endl;
        exit(1);
    }
    return k;
}

//将key值转换成十六进制
string toHex(key_t k)
{
    
    
    char buffer[64];
    snprintf(buffer,sizeof(buffer),"0x%x",k);
    return buffer;
}

simple test
insert image description here

This way we get the same key value.
The next step is to create the memory space.

Because only the last parameter is different between creating shared memory and obtaining shared memory, we can perform certain encapsulation

//进行封装
static int createShmHelper(key_t key,int size,int flag)
{
    
    
    int shmid = shmget(key,size,flag);

    //出错判断
    if(shmid==-1)
    {
    
    
        cerr<<"error: "<<errno<<" : "<<strerror(errno)<<endl;
        exit(2);
    }
    return shmid;
}

//创建共享内存
int createShm(key_t key,int size)
{
    
    
    //因为是创建,我们就用,保证创建最新的内存空间
    return createShmHelper(key,size,IPC_CREAT | IPC_EXCL);
}

//获取共享内存
int getShm(key_t key,int size)
{
    
    
    //只要获取就好,所以只要IPC_CREAT
    return createShmHelper(key,size,IPC_CREAT);
}

simple test
insert image description here

4. View and delete shared memory (instruction)

We have successfully created the shared memory, then there is a question: our two programs are very simple, there is no task loop, and it will end after running once, then if we run 相应创建的共享内存还存在吗?
shmServer again, we will find the following phenomenon
insert image description here
because in shmServer.cpp, we Calling shmget() uses IPC_CREAT | IPC_EXCL, so when the shared memory already exists, it will fail to create, return -1, and set the error code.

==================================================================================

共享内存的查看

We can also use ipcsinstructions to view information related to inter-process communication.
insert image description here
The first is the message queue, the second is the shared memory, and the third is the semaphore array. The
ipcs -minstruction means only viewing the shared memory.
insert image description here

key: the key value corresponding to the shared memory, 类比文件inode编号, kernel use
shmid: the id of the shared memory, 类比文件描述符fd, user use
owner: the user who created the shared memory
perms: the permission of the shared memory (same as the file)
bytes: size (in bytes)
nattch: association (link ) the number of processes that share memory
status:

Both of the above phenomena indicate that即使创建共享内存的进程已经退出,相应的共享内存其实还存在。

==================================================================================

共享内存的删除
We can ipcrm -m shmiddelete the shared memory we created by
insert image description here
我们再创建共享内存就会分配新的shmid给我们创建的共享内存了
insert image description here

5. Modify/delete shared memory

The function is: shmctl()
insert image description here
the first parameter is shmid; the second is yes 共享内存的操作, there are many kinds of operations; 删除,修改个别属性...the third parameter 输出型参数is the shared memory management in the kernel 结构体, you can pass the structure获取该共享内存的属性

This is part of the properties of the structure
insert image description here

共享内存的删除
The macro for the modification operation isIPC_RMID

//删除共享内存
void delShm(int shmid)
{
    
    

    int n=shmctl(shmid,IPC_RMID,NULL);
    assert(n!=-1);
    (void)n;
}

==================================================================================

获取共享内存属性

//查看共享内存属性
struct shmid_ds ds;
int n=shmctl(shmid,IPC_STAT,&ds);
if(n!=-1)
{
    
    
    cout<<"perm: "<<toHex(ds.shm_perm.__key)<<endl;
    cout<<"create pid: "<<ds.shm_cpid<<" : "<<getpid()<<endl;
}

insert image description here
Note: Permission is required to view shared memory
调用者必须要有这个共享内存的读权限
insert image description here

6. Shared memory permissions

We use the above method to create a shared memory, perms is the permission, the default is 0
insert image description here

Permissions need to be determined at the time of creation. In fact, you only need to add the corresponding permissions to the third parameter of shmget.

//创建共享内存
int createShm(key_t key,int size)
{
    
    
    //因为是创建,我们就用,保证创建最新的内存空间
    umask(0);//将掩码设置为0,保证预期的权限
    return createShmHelper(key,size,IPC_CREAT | IPC_EXCL | 0666);
}

insert image description here
This successfully sets the permissions.

7. Association of shared memory

Above we have completed the peripheral work of inter-process communication, but we have not really realized the communication. We 只创建了共享内存, but in fact, the shared memory is not in the task struct of our process at this time, we just created it successfully. 关联这个共享内存For this reason , we still need to 将共享内存映射到进程的共享区use it before we can really use it.

The associated function is shmat()
insert image description here

The first parameter is shmid; the second parameter is 共享区的虚拟地址, you can specify to mount the shared memory to the specified location through this parameter; the third parameter is 挂接方式(读写)
the return value is the virtual address of the mounted shared area

//关联共享内存
char * attchShm(int shmid)
{
    
    
    char*start=(char*)shmat(shmid,NULL,0);
    return start;
}

insert image description here
In (3), we talked about, nattch是关联该共享内存的进程数, and this test also verified this point. 0->1->2->1->0

Eight. The association of shared memory

The associated function isshmdt()

The header file is shmat()the same as
insert image description here
传参是shmat的返回值

//取关联共享内存
void detachShm(char*start)
{
    
    
    int n=shmdt(start);
    assert(n!=-1);
    (void)n;
}

Nine. Shared memory communication

Next, we can communicate using shared memory.
However, we can also encapsulate the above code into a class

#define SERVER 1
#define CLIENT 0
const int gsize=4096;

class Init
{
    
    
public:
    Init(int t):type(t)
    {
    
    
        //获取key值
        key_t k = getKey();
        //创建/获取共享内存
        if(type == SERVER)
        {
    
    
            //服务端创建
            shmid = createShm(k, gsize);
        }
        else
        {
    
    
            //客户端获取
            shmid = getShm(k, gsize);
        }
        //关联共享内存
        start = attachShm(shmid);
    }

    //获取读写字符串
    char *getStart()
    {
    
     
        return start; 
    }

    ~Init()
    {
    
    
        //取关联
        detachShm(start);

        if(type == SERVER)
        {
    
    
            //如果是服务端,还需要销毁共享内存
            delShm(shmid);
        }
    }
private:
    char *start;//读写字符串
    int type; //表示是服务端还是客户端
    int shmid;//共享内存的id
};

Use as follows:
insert image description here
insert image description here
communication completed successfully

10. Little knowledge

  1. 共享内存的大小分配
    insert image description here
    The size of PAGE_SIZE is 4KB, which just corresponds to the size of the data block accessed by the CPU.
    But when we create a shared memory of, for example, 5000 bytes, does the operating system allocate 8KB?
    insert image description here
    The size of the shared memory is still 5000, not 8KB.
    But this 5000 is actually just 允许访问的大小, actually 操作系统是分配了8KB的.

  2. Because the shared memory reads and writes data directly in the memory, 没有像管道那样的缓冲区if one party writes, the other party can read it immediately, so yes 所有进程通信速度最快的.

  3. Because shared memory communicates directly in memory, there is no system call interface, 没有任何保护机制yes同步互斥

conclusion

The knowledge record in this article is complicated, please understand. For the purpose of taking notes and sharing, Wang Lao gave pointers.

If you think this article is helpful to you, you might as well like it to support the blogger, please, this is really important to me.
insert image description here

Guess you like

Origin blog.csdn.net/m0_72563041/article/details/130212907