进程间通信--共享内存

进程间通信--共享内存,第1张

进程间通信--共享内存

2.共享内存
共享内存是3个IPC机制中的第二个。它允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间传递数据的一种非常有效的方式。实现共享内存常用的函数有:
#include

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 shmget(key_t key, size_t size, int shmflg);

(1) shmget函数

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

第一个参数与信号量一样,需要提供一个参数key,它有效地为共享内存命名,此函数返回一个共享内存标识符,用于后面的函数。

第二个参数指定需要共享的内存容量。

第三个参数shmflg包含9个比特的权限标识。

(2)shmat函数

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

启用对共享内存的访问,连接到一个进程的地址空间中。

第一个参数时标识符。

第二个参数指定的时共享内存连接到当前进程中的地址位置。它通常是一个空指针,表示让系统来选择地址。

第三个参数shmflg时一组位标志,权限标志。

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

(3)shmdt函数

int shmdt(const void *shm_addr);

它的作用时将共享内存从当前进程中分离。它的参数时shmat返回的地址指针。成功时返回0,失败时返回-1.

(4)shmctl函数

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

第一个参数是标识符

第二个参数command是要采取的动作。

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

还是用一个实现共享内存的例子来加深理解:

shm_com.h

#define TEXT_SZ 2048

struct shared_use_st {
    int written_by_you;
    char some_text[TEXT_SZ];
};

消费者程序:shm1.c

#include 
#include 
#include 
#include 

#include 

#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 failedn");
        exit(EXIT_FAILURE);
    }



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

    printf("Memory attached at %Xn", (int)shared_memory);



    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 ); 
            shared_stuff->written_by_you = 0;
            if (strncmp(shared_stuff->some_text, "end", 3) == 0) {
                running = 0;
            }
        }
    }



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

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

    exit(EXIT_SUCCESS);
}

生产者程序:shm2.c

#include 
#include 
#include 
#include 

#include 

#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 failedn");
        exit(EXIT_FAILURE);
    }

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

    printf("Memory attached at %Xn", (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 failedn");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

输出结果如下:

这里我们用的简陋的同步标志written_by_you,它包括一个缺乏效率的忙等待。但在实际编程中,我们应该使用信号量(V *** 作唤醒另一个进程的读 *** 作)或通过传递消息(管道的写 *** 作唤醒另一个进程的读 *** 作或IPC消息)、生成信号的方法来提供同步机制。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5636129.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存