亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 3058 | 回復: 2
打印 上一主題 下一主題

進程通信之--共享內(nèi)存 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-01-23 09:29 |只看該作者 |倒序瀏覽

                                進程通信之--共享內(nèi)存
    共享內(nèi)存是最快的進程通信的形式,因為通過它進程間的通信可以不經(jīng)過內(nèi)核,而是在進程的內(nèi)存空間中進行。從而加快了訪問內(nèi)存的速度。
    共享內(nèi)存需要某種形式的同步;
    共享內(nèi)存可以用于不同進程間的信息交換。
1, 文件內(nèi)存映射
    通過把文件映射到內(nèi)存區(qū),可以不用文件操作的I/O函數(shù)write,read等,而可以直接操作內(nèi)存。
(1)
               
               
                /*
* incr1.c
* 說明:該代碼達不到預期的目的
*/
#include    "my_unpipc.h"
#define    SEM_NAME    "mysem1"
int        count = 0;
int
main(int argc, char **argv)
{
    int        i, nloop;
    sem_t    *mutex;
    if (argc != 2) {
        fprintf(stderr, "usage: incr1 \n");
        exit(0);
    }
    nloop = atoi(argv[1]);
    /*
     * create, initialize, and unlink semaphore
     * mysem1 將會被創(chuàng)建在/dev/shm/sem.mysem1
     */
    mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1);
    if (mutex == SEM_FAILED) {
        perror("sem_open()");   
        exit(0);   
    }
    sem_unlink(SEM_NAME);
    setbuf(stdout, NULL);    /* stdout is unbuffered */
    if (fork() == 0) {        /* child */
        for (i = 0; i  nloop; i++) {
            sem_wait(mutex);
            printf("child: %d\n", count++);
            sem_post(mutex);
        }
        exit(0);
    }
    /* parent */
    for (i = 0; i  nloop; i++) {
        sem_wait(mutex);
        printf("parent: %d\n", count++);
        sem_post(mutex);
    }
    exit(0);
}
*運行演示:
[nobody@linux shm]$ ./incr1 3
child: 0
child: 1
child: 2
parent: 0
parent: 1
parent: 2
...
*結果分析   
   該程序中父子進程各自都有自己的count的拷貝,所以雖然各自可以互斥的對count進行加1操作,但加的都是各自的count變量。
(2)
/*
* incr2.c
* 說明:父子程序共享文件映射的內(nèi)存區(qū)塊。
* 所以父子進程所作的改動都會在文件映射的內(nèi)存中反應出來。
*/
#include    "my_unpipc.h"
#define    SEM_NAME    "mysem"
int
main(int argc, char **argv)
{
    int        fd, i, nloop, zero = 0;
    int        *ptr;
    sem_t    *mutex;
    if (argc != 3) {
        printf("usage: incr2  \n");
        exit(0);
    }
    nloop = atoi(argv[2]);
    /* open file, initialize to 0, map into memory */
    fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE);
    write(fd, &zero, sizeof(int));
    /*注意mmap函數(shù)的參數(shù) MAP_SHARED, 具體參見man mmap */
    ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    close(fd);
    /* create, initialize, and unlink semaphore  for mutex */
    mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1);
    if (mutex == SEM_FAILED) {
        perror("sem_open");
        exit(0);
    }
    /* 注意,退出時清理信號量文件 */
    sem_unlink(SEM_NAME);
    setbuf(stdout, NULL);    /* stdout is unbuffered */
    if (fork() == 0) {        /* child */
        for (i = 0; i  nloop; i++) {
            sem_wait(mutex);
            printf("child: %d\n", (*ptr)++);
            sem_post(mutex);
        }
        exit(0);
    }
    /* parent */
    for (i = 0; i  nloop; i++) {
        sem_wait(mutex);
        printf("parent: %d\n", (*ptr)++);
        sem_post(mutex);
    }
    exit(0);
}
運行效果:
[nobody@linux shm]$ ./incr2 mysem 3
child: 0
child: 1
child: 2
parent: 3
parent: 4
parent: 5
...
運行結果分析:
   由于父進程打開了文件,fork后,他們都各自有了該文件的描述符,文件被映射到內(nèi)存后,他們各自都有指針變量ptr,但該指針變量指向同一塊內(nèi)存。
(3) 把共享的變量放到一個結構中
    若把信號量變量放到進程的共享內(nèi)存區(qū),那么多個進程都可以看到它。這樣就可以使用sem_init而不使用sem_open在共享內(nèi)存區(qū)創(chuàng)建信號量,由于該信號量是共有的,而不是各自復制的,所以能夠達到互斥的目的。
#include    "my_unpipc.h"
struct shared {
  sem_t    mutex;        /* the mutex: a Posix memory-based semaphore */
  int    count;        /* and the counter */
} shared;
int
main(int argc, char **argv)
{
    int        fd, i, nloop;
    struct shared     *ptr;
    if (argc != 3) {
        printf("usage: incr3  \n");
        exit(0);
    }
    nloop = atoi(argv[2]);
    /*
     * 這里也可以用匿名的mmap,可以避免創(chuàng)建文件,還要刪除文件的操作。
      * (1)
     * ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
     * 或
     * (2)
       * fd = open("/dev/zero", O_RDWR)
     * ptr = mman(NULL, sizeof(int), PROT_READ | PROT_WRITE,
     *                 MAP_SHARED, fd, 0)
     * 然后用 (*ptr)++ ;
     */
    /* open file, initialize to 0, map into memory */
    fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE);
    write(fd, &shared, sizeof(struct shared));
    ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE,
               MAP_SHARED, fd, 0);
    close(fd);
    /* initialize semaphore that is shared between processes */
    sem_init(&ptr->mutex, 1, 1);
    setbuf(stdout, NULL);    /* stdout is unbuffered */
    if (fork() == 0) {        /* child */
        for (i = 0; i  nloop; i++) {
            sem_wait(&ptr->mutex);
            printf("child: %d\n", ptr->count++);
            sem_post(&ptr->mutex);
        }
        exit(0);
    }
    /* parent */
    for (i = 0; i  nloop; i++) {
        sem_wait(&ptr->mutex);
        printf("parent: %d\n", ptr->count++);
        sem_post(&ptr->mutex);
    }
    exit(0);
}
2, Posix 共享內(nèi)存
    Posix共享內(nèi)存的作用和前面的文件的映射來共享內(nèi)存的作用是一樣的,只是調用的函數(shù)不一樣,也不需要調用open來打開文件。
    Posix共享內(nèi)存的創(chuàng)建分為以下幾步:
    1) fd = shm_open()   
    2) ptr = mmap(..., fd, ...)
    3) ftruncate(fd, length);
    4) close(fd);   
注意:posix共享內(nèi)存的生命周期是隨內(nèi)核的。所以,創(chuàng)建完成后會在系統(tǒng)中一直存在。
2.1 posix共享內(nèi)存用于存放互斥變量來實現(xiàn)多個進程間的互斥
/*
* pxshm_incr3.c
* 用posix共享內(nèi)存實現(xiàn)進程間的互斥。
*/
#include    "my_unpipc.h"
struct shared {
  sem_t    mutex;        /* the mutex: a Posix memory-based semaphore */
  int    count;        /* and the counter */
} shared;
int
main(int argc, char **argv)
{
    int        fd, i, nloop;
    struct shared     *ptr;
    if (argc != 3) {
        printf("usage: incr3  \n");
        exit(0);
    }
    nloop = atoi(argv[2]);
    /*
      * 這是為了避免命名沖突的權益之計
      * 如果這里不做這一步,記得在程序退出的時候刪除共享內(nèi)存變量。
      */
    shm_unlink(argv[1]);   
    /* create shm, set its size, map it, close descriptor */
    fd = shm_open(argv[1], O_RDWR | O_CREAT | O_EXCL, FILE_MODE);
    if (fd == -1) {
        perror("shm_open");
        exit(0);
    }
    ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE,
               MAP_SHARED, fd, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(0);
    }
    ftruncate(fd, sizeof(struct shared));
    close(fd);
    /* initialize semaphore that is shared between processes */
    sem_init(&ptr->mutex, 1, 1);
    setbuf(stdout, NULL);    /* stdout is unbuffered */
    if (fork() == 0) {        /* child */
        for (i = 0; i  nloop; i++) {
            sem_wait(&ptr->mutex);
            printf("child: %d\n", ptr->count++);
            sem_post(&ptr->mutex);
        }
        exit(0);
    }
    /* parent */
    for (i = 0; i  nloop; i++) {
        sem_wait(&ptr->mutex);
        printf("parent: %d\n", ptr->count++);
        sem_post(&ptr->mutex);
    }
    exit(0);
}
執(zhí)行的效果如下所示:
[hover@jsdhover pxshm]$ ./pxshm_incr3 hover 3
child: 0
child: 1
child: 2
parent: 3
parent: 4
parent: 5
2.2 用于多(clients)對一(server)間的進程通信
    由于posix共享內(nèi)存是文件形式,所以對于沒有親緣關系的進程也可以訪問,這樣我們就可以實現(xiàn)多個進程間的通信。
3, system v共享內(nèi)存
v共享內(nèi)存在現(xiàn)在的編程中使用得比較多,于posix共享內(nèi)存相比,
    posix  :     shm_open() --> mmap()   
    system v :    shmget() ---> shmat()
System V共享內(nèi)存的使用中不創(chuàng)建臨時文件,使用起來比較方便?捎糜诙噙M程和多線程間的同步。 下面看一個例子:
#define TEXT_SIZE 2048
struct shared_use_at {
   int written_by_you;
   char some_txt[TEXT_SIZE];
}
/*
* Producer
*/
#include "my_unpipc.h"
#include "shm_com.h"
int
main(void)
{
    int running = 1;
    void *shared_mem = (void *)0;   
    struct shared_use_at *shared_stuff;
    char buffer[BUFSIZ];   
    int shmid;
   
    /* 這里用0666權限創(chuàng)建一個共享內(nèi)存區(qū) */
    shmid = shmget((key_t)KEY_INT, sizeof(struct shared_use_at), 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(0);
    }
    /* 把共享內(nèi)存的首地址連接到調用進程的地址空間 */
    shared_mem = shmat(shmid, (void *)0, 0);
    if (shared_mem == (void *)-1) {
        perror("shmat");
        exit(0);
    }
    printf("Memory attached at %X\n", (int)shared_mem);
    shared_stuff = (struct shared_use_at *)shared_mem;
    /*
      * Begin to produce.
      */
    while (running) {
        while (shared_stuff->written_by_you == 1) {     /* waiting */
            sleep(1);
            printf("Waitring for client...\n");
        }
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
      
        strncpy(shared_stuff->some_text, buffer, TEXT_SIZE);
        shared_stuff->written_by_you = 1;
      
        if (strncmp(buffer, "end", 3) == 0)
            running = 0;
    }
    /*
      * Retrieve shared memory.
      */
    if (shmdt(shared_mem) == -1) {
        perror("shmdt");
        exit(0);
    }
    /*
    if (shmctl(shmid, IPC_RMID, 0) == -1) {
        perror("shmctl");
        exit(0);
    }
    */
    exit(0);
}
/*
* consumer:
*/
#include "my_unpipc.h"
#include "shm_com.h"
int
main(void)
{
    int running = 1;
    void *shared_mem = (void *)0;   
    struct shared_use_at *shared_stuff;
    int shmid;
   
    srand((unsigned int)getpid());
   
    shmid = shmget((key_t)KEY_INT, sizeof(struct shared_use_at), 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(0);
    }
    shared_mem = shmat(shmid, (void *)0, 0);
    if (shared_mem == (void *)-1) {
        perror("shmat");
        exit(0);
    }
    printf("Memory attached at %X\n", (int)shared_mem);
   
    shared_stuff = (struct shared_use_at *)shared_mem;
    shared_stuff->written_by_you = 0;
    while (running) {
        if (shared_stuff->written_by_you) {
            printf("You wrote : %s\n", 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_mem) == -1) {
        perror("shmdt");
        exit(0);
    }
    if (shmctl(shmid, IPC_RMID, 0) == -1) {
        perror("shmctl");
        exit(0);
    }
    exit(0);
}
4, 遇到的問題
(1) sem_open() 找不到文件或路徑的問題
這是由于在內(nèi)核中,創(chuàng)建信號量的默認路徑是/dev/shm。當你要創(chuàng)建一個信號量/tmp/mysem時,實際上是創(chuàng)建了一個/dev/shm/sem.tmp/mysem,而這里由于/dev/shm/tmp目錄根本就不存在,所以會出錯。
解決方法:
    *直接寫信號量文件的名字,將會創(chuàng)建在/dev/shm中:sem_open("mysem", ...)
    *   
(...)
               
               
               
               


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/28197/showart_2158261.html

論壇徽章:
0
2 [報告]
發(fā)表于 2012-09-25 20:02 |只看該作者
牛人。
請問下,SYSTEM V的共享內(nèi)存周期是?

論壇徽章:
0
3 [報告]
發(fā)表于 2013-03-13 09:15 |只看該作者
very good !!!
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP