歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux管理 >> Linux網絡

linux網絡編程之System V 共享內存和系列函數

跟消息隊列一樣,共享內存也有自己的數據結構,如下:

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 */

...

};

同樣地,第一個成員是共有的IPC內核數據結構,其余是私有成員。

以下是幾個共享內存函數 :

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

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

功能:用來創建共享內存

原型 int shmget(key_t key, size_t size, int shmflg);

參數

key:這個共享內存段名字

size:共享內存大小

shmflg:由 九個權限標志構成,它們的用法和創建文件時使用的mode模式標志是一樣的

返回值:成功返回一個非負整數,即該共享 內存段的標識碼;失敗返回-1

功能:將共享內存段連接到進程地址空間

原型

void *shmat(int shmid, const void *shmaddr, int shmflg);

參數

shmid: 共享內存標識

shmaddr:指定連接的地址

shmflg:它的兩個可能取值 是SHM_RND和SHM_RDONLY

返回值:成功返回一個指針,指向共享內存第一個字節;失敗返回-1

shmaddr為NULL,核 心自動選擇一個地址

shmaddr不為NULL且shmflg無SHM_RND標記,則以shmaddr為連接地址。

shmaddr不為NULL且shmflg 設置了SHM_RND標記,則連接的地址會自動向下調整為SHMLBA的整數倍。

公式:shmaddr - (shmaddr % SHMLBA)

shmflg=SHM_RDONLY,表示連接操作用來只讀共享內存

功能:將共享內存段與當前進程脫離

原型 int shmdt (const void *shmaddr);

參數

shmaddr: 由shmat所返回的指針

返回值:成功返回0;失敗返回-1

注意:將共享 內存段與當前進程脫離不等於刪除共享內存段

功能:用於控制共享內存

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

參數

shmid:由shmget返回的共享內存標識碼

cmd:將要采取的動作(有三個可取值)

buf:指向一個保存著共享內存的模式狀態和訪問權限的數據結構

返回值:成功返回0;失敗返回-1

cmd 的取值 如下,與消息隊列類似:

IPC_STAT 把shmid_ds結構中的數據設置為共享內存的當前關聯值

IPC_SET 在進程有足 夠權限的前提下,把共享內存的當前關聯值設置為shmid_ds數據結構中給出的值

IPC_RMID 刪除共享內存段

下面 寫兩個函數測試一下:

shm_write.c

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/ipc.h>
#include<sys/shm.h>
    
#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)
    
typedef struct stu
{
    char name[32];
    int age;
} STU;
    
int main(int argc, char *argv[])
{
    int shmid;
    shmid = shmget(1234, sizeof(STU), IPC_CREAT | 0666);
    if (shmid == -1)
        ERR_EXIT("shmget");
    
    STU *p;
    p = shmat(shmid, NULL, 0);
    if (p == (void *) - 1)
        ERR_EXIT("shmat");
    
    strcpy(p->name, "lisi");
    p->age = 20;
    
    shmdt(p);
    
    return 0;
}

在上面程序中,先創建一塊共享內存,再映射到進程的地址空間。

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./shm_write

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -m

------ Shared Memory Segments -- ------

key        shmid      owner      perms      bytes      nattch     status      

0x000004d2     0          simba      666           36            0                      

可以看到創建了一塊共享內存,字節數為寫入的STU大小,natth 表示進程連接個數,若在上面程序的 shmdt 之前sleep(n); 此時在另一窗口觀察,可發現連接數為1,進程退出時,連接數再次為0。

shm_read.c

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/ipc.h>
#include<sys/shm.h>
    
#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)
    
typedef struct stu
{
    char name[32];
    int age;
} STU;
    
int main(int argc, char *argv[])
{
    int shmid;
    shmid = shmget(1234, 0, 0);
    if (shmid == -1)
        ERR_EXIT("shmget");
    
    STU *p;
    p = shmat(shmid, NULL, 0);
    if (p == (void *) - 1)
        ERR_EXIT("shmat");
    
    printf("name = %s age = %d\n", p->name, p->age);
    
    shmdt(p);
    
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}

上面程序中,先打開共享內存,若未知共享內存大小,size 可設為0,然後也映射到自身的進程地址空間,讀取數據, 最後使用shmctl 刪除這段共享內存。

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./shm_read

name = lisi age = 20

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs - m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status

共享內存段已經被刪除。

Copyright © Linux教程網 All Rights Reserved