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

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 3057 | 回復(fù): 2
打印 上一主題 下一主題

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

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

                                進(jìn)程通信之--共享內(nèi)存
    共享內(nèi)存是最快的進(jìn)程通信的形式,因?yàn)橥ㄟ^(guò)它進(jìn)程間的通信可以不經(jīng)過(guò)內(nèi)核,而是在進(jìn)程的內(nèi)存空間中進(jìn)行。從而加快了訪問(wèn)內(nèi)存的速度。
    共享內(nèi)存需要某種形式的同步;
    共享內(nèi)存可以用于不同進(jìn)程間的信息交換。
1, 文件內(nèi)存映射
    通過(guò)把文件映射到內(nèi)存區(qū),可以不用文件操作的I/O函數(shù)write,read等,而可以直接操作內(nèi)存。
(1)
               
               
                /*
* incr1.c
* 說(shuō)明:該代碼達(dá)不到預(yù)期的目的
*/
#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 將會(huì)被創(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);
}
*運(yùn)行演示:
[nobody@linux shm]$ ./incr1 3
child: 0
child: 1
child: 2
parent: 0
parent: 1
parent: 2
...
*結(jié)果分析   
   該程序中父子進(jìn)程各自都有自己的count的拷貝,所以雖然各自可以互斥的對(duì)count進(jìn)行加1操作,但加的都是各自的count變量。
(2)
/*
* incr2.c
* 說(shuō)明:父子程序共享文件映射的內(nèi)存區(qū)塊。
* 所以父子進(jìn)程所作的改動(dòng)都會(huì)在文件映射的內(nèi)存中反應(yīng)出來(lá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, 具體參見(jiàn)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);
    }
    /* 注意,退出時(shí)清理信號(hào)量文件 */
    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);
}
運(yùn)行效果:
[nobody@linux shm]$ ./incr2 mysem 3
child: 0
child: 1
child: 2
parent: 3
parent: 4
parent: 5
...
運(yùn)行結(jié)果分析:
   由于父進(jìn)程打開(kāi)了文件,fork后,他們都各自有了該文件的描述符,文件被映射到內(nèi)存后,他們各自都有指針變量ptr,但該指針變量指向同一塊內(nèi)存。
(3) 把共享的變量放到一個(gè)結(jié)構(gòu)中
    若把信號(hào)量變量放到進(jìn)程的共享內(nèi)存區(qū),那么多個(gè)進(jìn)程都可以看到它。這樣就可以使用sem_init而不使用sem_open在共享內(nèi)存區(qū)創(chuàng)建信號(hào)量,由于該信號(hào)量是共有的,而不是各自復(fù)制的,所以能夠達(dá)到互斥的目的。
#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)建文件,還要?jiǎng)h除文件的操作。
      * (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)存的作用和前面的文件的映射來(lái)共享內(nèi)存的作用是一樣的,只是調(diào)用的函數(shù)不一樣,也不需要調(diào)用open來(lái)打開(kāi)文件。
    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)建完成后會(huì)在系統(tǒng)中一直存在。
2.1 posix共享內(nèi)存用于存放互斥變量來(lái)實(shí)現(xiàn)多個(gè)進(jìn)程間的互斥
/*
* pxshm_incr3.c
* 用posix共享內(nèi)存實(shí)現(xiàn)進(jì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]);
    /*
      * 這是為了避免命名沖突的權(quán)益之計(jì)
      * 如果這里不做這一步,記得在程序退出的時(shí)候刪除共享內(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)對(duì)一(server)間的進(jìn)程通信
    由于posix共享內(nèi)存是文件形式,所以對(duì)于沒(méi)有親緣關(guān)系的進(jìn)程也可以訪問(wèn),這樣我們就可以實(shí)現(xiàn)多個(gè)進(jì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)建臨時(shí)文件,使用起來(lái)比較方便?捎糜诙噙M(jìn)程和多線程間的同步。 下面看一個(gè)例子:
#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權(quán)限創(chuàng)建一個(gè)共享內(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)存的首地址連接到調(diào)用進(jìn)程的地址空間 */
    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, 遇到的問(wèn)題
(1) sem_open() 找不到文件或路徑的問(wèn)題
這是由于在內(nèi)核中,創(chuàng)建信號(hào)量的默認(rèn)路徑是/dev/shm。當(dāng)你要?jiǎng)?chuàng)建一個(gè)信號(hào)量/tmp/mysem時(shí),實(shí)際上是創(chuàng)建了一個(gè)/dev/shm/sem.tmp/mysem,而這里由于/dev/shm/tmp目錄根本就不存在,所以會(huì)出錯(cuò)。
解決方法:
    *直接寫信號(hào)量文件的名字,將會(huì)創(chuàng)建在/dev/shm中:sem_open("mysem", ...)
    *   
(...)
               
               
               
               


本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/28197/showart_2158261.html

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

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

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

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP