Linux共享内存

共享内存是有IPC为进程创建的一个特殊的地址范围,它将出现在该进程的地址的空间中。

共享内存使用的函数类似与信号量的函数,它的定义如下:

#include<sys/shm.h>

void *shmat(int shm_id , const void *shm_addr , int shmflg);

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

int shmdt(const void *shm_addr);

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

1.shmget函数

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

与信号量一样,程序需要提供一个参数key,它有效地共享内存段命名、shmget函数返回一个共享内存标识符,该标识符将用于后续的共享内存函数。有一个特殊的键值IPC_PRIVATE,它用于创建一个值属于创建进程的共享内存、

第二个参数size以字节为单位指定需要共享的内存的容量。

第三个参数shmflg包含9个比特的权限标识,他们的作用与创建文件时使用的mode标志一样。

2.shmat函数

第一次创建共享内存段时,它不能被任何进程访问。要想启用对该共享内存的访问,必须将其连接到一个进程的地址空间中。这项任务由shmat完成。

void *shmat(int shm_id , const void *shm_addr , int shmflg);

第一个参数shm_id是由shmget返回的共享内存标示符。

第二个参数shm_addr指定的是共享内存连接到当前进程中的地址位置。

第三个参数shmflg是一组位标志,它的两个取值是SHM_RND(这个标志与shm_addr联合使用,用来控制共享内存连接的地址)和SHM_RDONLY(它使得连接的内存只读)。

如果shmat调用成功,它返回一个指向共享内存第一个字节的指针。如果失败,它就返回-1.

3.shmdt函数

它的作用是将共享内存从当前进程中分离。注意,分离共享内存并未删除它,只是使得该共享内存对当前进程不再可用。

4.shmctl

与复杂的信号量控制函数相比,共享内存的控制函数要稍微简单一下。

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

shmid_ds结构至少包含以下成员:

struct shmid_ds

{

uid_t shm_perm.uid;

uid_t shm_perm.gid;

mode_t shm_perm.mode;

}

第一个参数shm_id是shmget返回的共享内存标识符。

第二个参数command是采取的动作,它可以取三个值

IPC_STAT                    把shmid_ds结构中的数据设置为共享内存的当前关联值。

IPC_SET                      如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值、

IPC_RMID                   删除共享内存段

第三个参数buf是一个指针,它指向包含共享内存模式和访问权限的结构。

/* Our first program is a consumer. After the headers the shared memory segment
 (the size of our shared memory structure) is created with a call to shmget,
 with the IPC_CREAT bit specified. */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/shm.h>

#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;
    int shmid;

    srand((unsigned int)getpid());    

    shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);

    if (shmid == -1) {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }

/* We now make the shared memory accessible to the program. */

    shared_memory = shmat(shmid, (void *)0, 0);
    if (shared_memory == (void *)-1) {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }

    printf("Memory attached at %X\n", (int)shared_memory);

/* The next portion of the program assigns the shared_memory segment to shared_stuff,
 which then prints out any text in written_by_you. The loop continues until end is found
 in written_by_you. The call to sleep forces the consumer to sit in its critical section,
 which makes the producer wait. */

    shared_stuff = (struct shared_use_st *)shared_memory;
    shared_stuff->written_by_you = 0;
    while(running) {
        if (shared_stuff->written_by_you) {
            printf("You wrote: %s", shared_stuff->some_text);
            sleep( rand() % 4 ); /* make the other process wait for us ! */
            shared_stuff->written_by_you = 0;
            if (strncmp(shared_stuff->some_text, "end", 3) == 0) {
                running = 0;
            }
        }
    }

/* Lastly, the shared memory is detached and then deleted. */

    if (shmdt(shared_memory) == -1) {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }

    if (shmctl(shmid, IPC_RMID, 0) == -1) {
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

/* The second program is the producer and allows us to enter data for consumers.
 It's very similar to shm1.c and looks like this. */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/shm.h>

#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;
    char buffer[BUFSIZ];
    int shmid;

    shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);

    if (shmid == -1) {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }

    shared_memory = shmat(shmid, (void *)0, 0);
    if (shared_memory == (void *)-1) {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }

    printf("Memory attached at %X\n", (int)shared_memory);

    shared_stuff = (struct shared_use_st *)shared_memory;
    while(running) {
        while(shared_stuff->written_by_you == 1) {
            sleep(1);            
            printf("waiting for client...\n");
        }
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
        
        strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
        shared_stuff->written_by_you = 1;

        if (strncmp(buffer, "end", 3) == 0) {
                running = 0;
        }
    }

    if (shmdt(shared_memory) == -1) {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}


你可能感兴趣的:(linux,struct,command,cmd,buffer,structure)