• linux IPC共享内存


    共享内存相关函数

    获得一个共享存储标识符

    #include <sys/ipc.h>
    #include <sys/shm.h
    
    int shmget(key_t key, size_t size, int shmflg);
    返回值:成功共享存储ID,失败-1
    key:函数ftok返回值或IPC_PRIVATE(适合用在有亲缘关系的进程中)

    size: 共享存储段的长度,以字节为单位
    shmflg:权限标志位

    共享存储段执行多种操作

    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    返回值:成功0错误-1
    shmid:共享内存标识符
    cmd:  IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
        IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode赋值到共享内存的shmid_ds结构中
        IPC_RMID:删除这些共享内存
    buf:共享内存管理结构体

     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 shmid_ds

    一旦创建了一个共享存储段,进程就可调用shmat将其连接到它的地址空间中

    #include <sys/types.h>
    #include <sys/shm.h>
    
    void *shmat(int shmid, const void *shmaddr, int shmflg);
    返回值:成功共享存储段的指针,失败-1
    shmid:共享内存标识符
    shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核决定
    shmflg:如果指定了SHM_RDONLY位,则以只读方式连接此段,否则以读写的方式连接此段。通常为0

    当对共享存储段的操作已经结束时,则调用shmdt与该段分离

    #include <sys/types.h>
    #include <sys/shm.h>
    
    int shmdt(const void *shmaddr);
    返回值:成功0,失败-1
    shmaddr:shmat返回的值

    程序例程,父子进程间通讯:

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/shm.h>
     4 #include <sys/ipc.h>
     5 #include <string.h>
     6 
     7 #define SIZE 1024
     8 
     9 int main()
    10 {
    11     int shmid;
    12     pid_t pid;
    13     char *shmaddr;
    14     int flag;
    15     struct shmid_ds buf;
    16 
    17     shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600);
    18     if(shmid < 0)
    19     {
    20         perror("get shm ipc_id error");
    21         return -1;
    22     }
    23 
    24     if((pid = fork()) < 0) {
    25         perror("get fork error");
    26         return -1;
    27     } else if(pid == 0) {       /* child */
    28         shmaddr = (char *)shmat(shmid, NULL, 0);
    29         if((int)shmaddr == -1)
    30         {
    31             perror("shmat error");
    32             return -1;
    33         }
    34         strcpy(shmaddr, "Hi,I am child process!
    ");
    35         shmdt(shmaddr);
    36         return 0;
    37     } else {                    /* parent */
    38         sleep(3);
    39         flag = shmctl(shmid, IPC_STAT, &buf);
    40         if(flag == -1)
    41         {
    42             perror("shmctl error");
    43             return -1;
    44         }
    45 
    46         printf("shm_segsz=%d bytes
    ", buf.shm_segsz);
    47         printf("parent pid=%d,shm_cpid=%d 
    ", getpid(), buf.shm_cpid);
    48         printf("child pid=%d,shm_lpid=%d
    ", pid, buf.shm_lpid);
    49         shmaddr = (char *)shmat(shmid, NULL, 0);
    50         if((int)shmaddr == -1)
    51         {
    52             perror("parent:shmat error");
    53             return -1;
    54         }
    55         printf("shmaddr in %s
    ", shmaddr);
    56         shmdt(shmaddr);
    57         shmctl(shmid, IPC_RMID, NULL);
    58     }
    59 
    60     return 0;
    61 }

    进程之间使用共享内存通讯:

    shmwrite.c

     1 #include <stdio.h>
     2 #include <sys/ipc.h>
     3 #include <sys/shm.h>
     4 #include <string.h>
     5 
     6 typedef struct {
     7         char name[8];
     8         int age;
     9 }people;
    10 
    11 int main()
    12 {
    13         int shmid;
    14         key_t key;
    15         char temp[8];
    16         char pathname[30];
    17         people *p_map;
    18         int i;
    19 
    20         strcpy(pathname, "/tmp");
    21         key = ftok(pathname, 0x03);
    22         if(key == -1)
    23         {
    24                 perror("ftok error
    ");
    25                 return -1;
    26         }
    27 
    28         printf("key=%d
    ", key);
    29         shmid = shmget(key, 4096,IPC_CREAT|IPC_EXCL|0600);
    30         if(shmid == -1)
    31         {
    32                 perror("shmget error
    ");
    33                 return -1;
    34         }
    35         printf("shmid=%d
    ",shmid);
    36 
    37         p_map = (people *)shmat(shmid, NULL, 0);
    38         if((int)p_map == -1)
    39         {
    40                 perror("shmat error
    ");
    41                 return -1;
    42         }
    43         memset(temp, 0x00, sizeof(temp));
    44         strcpy(temp, "test");
    45         temp[4] = '0';
    46 
    47         for(i=0;i<3;i++)
    48         {
    49                 temp[4]+=1;
    50                 strncpy((p_map+i)->name, temp, 5);
    51                 (p_map+i)->age=i;
    52         }
    53 
    54         if(shmdt(p_map) == -1)
    55         {
    56                 perror("shmdt error
    ");
    57                 return -1;
    58         }
    59         return 0;
    60 }

    shmread.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct {
            char name[8];
            int age;
    }people;
    
    int main(int argc, char *argv[])
    {
            int shmid;
            people *p_map;
            key_t key;
            char pathname[30];
            int i = 0;
    
            strcpy(pathname, "/tmp");
            key = ftok(pathname, 0x03);
            if(key == -1)
            {
                    perror("ftok error
    ");
                    return -1;
            }
            printf("key=%d
    ", key);
            shmid = shmget(key, 0, 0);
            if(shmid == -1)
            {
                    perror("shmread:shmget error
    ");
                    return -1;
            }
            printf("shmid=%d
    ",shmid);
            p_map = (people*)shmat(shmid, NULL, 0);
            for(i=0;i<3;i++)
            {
                    printf("name:%s
    ", (*(p_map+i)).name);
                    printf("age:%d
    ", (*(p_map+i)).age);
            }
            if(shmdt(p_map) == -1)
            {
                    perror("shmdt error
    ");
                    return -1;
            }
            return 0;
    }

    然后执行:

    gcc shmwrite.c -o shmwrite
    gcc shmread.c -o shmread
    ./shmwrite
    ./shmread
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    TCHAR字符串查找&反向查找字符串
    如何判断一个文本文件的编码
    用NETSH WINSOCK RESET命令修复网络
    #define和typedef在windows上的应用
    Visual Studio Code (vscode)编译C++
    win32 Message(MSG)消息处理
    HBRUSH to RGB value
    InvalidateRect和UpdateWindow
    Informatic ETL开发步骤
    【非官方方式】获取Disconf动态更新的配置文件的值
  • 原文地址:https://www.cnblogs.com/ch122633/p/8068152.html
Copyright © 2020-2023  润新知