日期:忘了。

关键词:Linux程序设计;System-V;进程通信;共享内存;消息队列。

一、共享内存

 

1.1 基本知识

(待补充)

 

1.2 代码

一个基于share memory实现的客户-服务模型。

  • shm_comm.h

#define TEXT_SZ 2048

struct shared_use_st

{

    int written_by_you;

    char some_text[TEXT_SZ];

};

typedef
struct shared_use_st shared_use_st;

  • shm1.c

 

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/shm.h>

#include "shm_com.h"

 

int main()

{

    int running = 1;

    void *shm_ptr = NULL;

    struct shared_use_st *shared_stuff;

    int shmid;

 

    srand((unsigned
int)getpid());

 

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

    printf("shmid = %x\n", shmid);

    if (shmid == -1)

    {

        fprintf(stderr, "shmget fail\n");

        exit(EXIT_FAILURE);

    }

    shm_ptr = shmat(shmid, NULL, 0);

    //该值应该是shm在当前进程空间中的虚拟地址,而不是shm真实的物理地址

    //所以shm1和shm2的返回值不一样

 

    if (shm_ptr == (void *)-1)

    {

        fprintf(stderr, "shmat failed\n");

        exit(EXIT_FAILURE);

    }

 

    printf("Memory attached at %p\n", shm_ptr);

 

    shared_stuff = (struct shared_use_st *)shm_ptr;

    shared_stuff->written_by_you = 0;

    while (running)

    {

        if (shared_stuff->written_by_you)

        {

            printf("You wrote %s\n", shared_stuff->some_text);

            sleep(5);

            shared_stuff->written_by_you = 0;

            if (strncmp(shared_stuff->some_text, "end", 3) == 0)

            {

                running = 0;

            }

        }

    }

 

    if(shmdt(shm_ptr) == -1)

    {

        fprintf(stderr, "shmdt failed\n");

        exit(EXIT_FAILURE);

    }

 

    if(shmctl(shmid, IPC_RMID, NULL) == -1)

    {

        fprintf(stderr, "shmctl(IPC_RMID) failed\n");

        exit(EXIT_FAILURE);

    }

    exit(EXIT_SUCCESS);

}

 

  • shm2.c

 

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/shm.h>

#include "shm_com.h"

 

int main()

{

    int running = 1;

    void *shm_ptr = NULL;

    struct shared_use_st *share_stuff;

    char buff[TEXT_SZ];

    int shmid;

 

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

    printf("shmid = %x\n", shmid);

    if(shmid == -1)

    {

        fprintf(stderr, "shmget failed\n");

        exit(EXIT_FAILURE);

    }

 

    shm_ptr = shmat(shmid, NULL, 0);

    if(shm_ptr == (void *)-1)

    {

        fprintf(stderr, "shmat failed\n");

        exit(EXIT_FAILURE);

    }

    printf("Memory attached at %p\n", shm_ptr);

 

    share_stuff = (struct shared_use_st*)shm_ptr;

 

    while(running)

    {

        if(share_stuff->written_by_you == 1)

        {

            sleep(1);

            printf("waiting for client\n");

        }

        printf("Enter texts:");

        fgets(buff, TEXT_SZ, stdin);

        strncpy(share_stuff->some_text, buff, TEXT_SZ);

        share_stuff->written_by_you = 1;

        
 

        if(strncmp(share_stuff->some_text, "end", 3) == 0)

        {

            running = 0;

        }

    }

 

    if(shmdt(shm_ptr) == -1)

    {

        fprintf(stderr, "shmdt failed\n");

        exit(EXIT_FAILURE);

    }

    exit(EXIT_SUCCESS);

 

}

  • 运行结果

二、消息队列

2.1 基本知识

待补充。

2.2 代码

  • msg1.c

 

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

 

#include <sys/msg.h>

struct msg_t

{

    long
int msg_type;

    char content[BUFSIZ];

};

 

int main()

{

    int running = 1;

    int msgid;

    long
表示获取队列第一个可用消息

    struct msg_t msg;

 

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

    printf("msgid = %d\n", msgid);

    if (msgid == -1)

    {

        fprintf(stderr, "msgget failed\n");

        exit(EXIT_FAILURE);

    }

 

    while (running)

    {

        if (msgrcv(msgid, (void *)&msg, BUFSIZ, msg_to_receive, 0) == -1)

        {

            fprintf(stderr, "msgrcv failde\n");

            exit(EXIT_FAILURE);

        }

        printf("You wrote %s", msg.content);

        if(strncmp(msg.content, "end", 3) == 0)

            running = 0;

    }

    if (msgctl(msgid, IPC_RMID, 0) == -1)

    {

        fprintf(stderr, "msgcntl failed\n");

        exit(EXIT_FAILURE);

    }

    exit(EXIT_SUCCESS);

 

}

 

 

  • msg2.c

 

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

#include <sys/msg.h>

#define MAX_TEXT 512

struct msg_t

{

    long
int msg_type;

    char content[BUFSIZ];

};

 

int main()

{

    int running = 1;

    struct msg_t msg;

    int msgid;

    char buffer[BUFSIZ];

 

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

    printf("msgid = %d\n", msgid);

 

    if (msgid == -1)

    {

        fprintf(stderr, "msgget failed\n");

        exit(EXIT_FAILURE);

    }

 

    while (running)

    {

        printf("Enter texts:");

        fgets(buffer, BUFSIZ, stdin);

        msg.msg_type = 1;

        strcpy(msg.content, buffer);

 

        if(msgsnd(msgid, (void *)&msg, BUFSIZ, 0) == -1)

        {

            fprintf(stderr, "msgsnd failed\n");

            exit(EXIT_FAILURE);

        }

        if(strncmp(msg.content, "end", 3) == 0)

        {

            running = 0;

        }

    }

 

    exit(EXIT_SUCCESS);

}

 

三、信号量

3.1 基本知识

待补充。

3.2 代码

  • semun.h

 

#if defined(__GNU_LIBRARY__) &&
!defined(_SEM_SEMUN_UNDEFINED)

    /* union semun is defined by including <sys/sem.h> */

#else

    /* according to X/OPEN we have to define it ourselves */

    union semun {

        int val; /* value for SETVAL */

        struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */

        unsigned
short
int *array; /* array for GETALL, SETALL */

        struct seminfo *__buf; /* buffer for IPC_INFO */

    };

#endif

 

 

  • sema.c

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/sem.h>

#include "semun.h"

 

static
int sem_id;

static
int set_semvalue()

{

    union semun sem_union;

    sem_union.val = 1;

    if (semctl(sem_id, 0, SETVAL, sem_union) == -1)

        return
0;

    return
1;

}

static
void del_semvalue()

{

    union semun sem_union;

    if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

        fprintf(stderr, "Fail to delete semaphore\n");

}

static
int sema_p()

{

    struct sembuf sem_b;

    sem_b.sem_num = 0;//信号量编号,除非是一组信号量,否则0

    sem_b.sem_op = -1;//-1操作

    sem_b.sem_flg = SEM_UNDO;//与操作系统对信号量的操作相关,一般是UNDO

    if (semop(sem_id, &sem_b, 1) == -1)

    {

        fprintf(stderr, "sema_p failed\n");

        return
0;

    }

    return
1;

}

static
int sema_v()

{

    struct sembuf sem_b;

    sem_b.sem_num = 0;

    sem_b.sem_op = 1;

    sem_b.sem_flg = SEM_UNDO;

    if (semop(sem_id, &sem_b, 1) == -1)

    {

        fprintf(stderr, "sema_v failed\n");

        return
0;

    }

    return
1;

}

 

int main(int argc, char *argv[])

{

    int i;

    int pause_time;

    char op_char = 'O';

    srand((unsigned
int)getpid());

    sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);

    if (argc > 1)

    {

        if(set_semvalue() == 0)

        {

            fprintf(stderr, "init fail\n");

            exit(EXIT_FAILURE);

        }

        op_char = 'X';

        sleep(2);

    }

 

    for (i = 0; i < 10; i++)

    {

        if (sema_p() == 0)

            exit(EXIT_FAILURE);

        printf("%c", op_char);

        fflush(stdout);

 

        pause_time = rand() % 3;

        sleep(pause_time);

        printf("%c", op_char);

        fflush(stdout);

 

        if (!sema_v())

            exit(EXIT_FAILURE);

        pause_time = rand() % 2;

        sleep(pause_time);

    }

    printf("\n%d - finished\n", getpid());

    if (argc > 1)

    {

        sleep(10);

        del_semvalue();

    }

    exit(EXIT_SUCCESS);

}

Linux程序设计:进程通信的更多相关文章

  1. Linux下进程通信的八种方法

    Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...

  2. Linux之进程通信20160720

    好久没更新了,今天主要说一下Linux的进程通信,后续Linux方面的更新应该会变缓,因为最近在看Java和安卓方面的知识,后续会根据学习成果不断分享更新Java和安卓的方面的知识~ Linux进程通 ...

  3. Linux下进程通信之管道

    每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把 ...

  4. Linux:进程通信之消息队列Message实例

    /*send.c*/ /*send.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h&g ...

  5. Linux编程---进程通信

    Linux的通信方式主要有分类有以下几种: -匿名管道和FIFO有名管道 -消息队列,信号量和共享存储 -套接字 对于套接字的进程通信,我就留在套接字的文章中再写了. 一.管道 管道是最古老的进程通信 ...

  6. linux之间进程通信

    进程间通信方式:                    同主机进程间数据交换机制: pipe(无名管道) / fifo(有名管道)/ message queue(消息队列)和共享内存. 必备基础: f ...

  7. [置顶] 简单解析linux下进程通信方法

    linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的.而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  8. linux程序设计--进程相关的各种ID

    1.调用exec函数时,目标可执行文件没有设定设置用户id. 2.调用exec函数时,目标可执行文件设定设置用户id.  

  9. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

  10. 进程以及进程通信(IPC)类型

    这里用我有限的知识来解释同时参考了一些其他博主的子类,希望能给与一部分入门的朋友一个清晰的理解,有问题之处还请指出 首先简单谈一下什么是进程? 答:进程是装入内存运行的程序段,是许多的系统对象拥有权的 ...

随机推荐

  1. java学习笔记(四):import语法

    Import 语法是给编译器寻找特定类的适当位置的一种方法. 创建一个Employee 类,包括四个实体变量姓名(name),年龄(age),职位(designation)和薪水(salary). p ...

  2. FortiGate安全策略说明

    1.安全策略原理 1)为了对数据流进行统一控制,方便用户配置和管理,FGT设备引入了安全策略的概念.通过配置安全策略,防火墙能够对经过设备的数据流进行有效的控制和管理. 2)当防火墙收到数据报文时,把 ...

  3. eclipse装了springboot插件后yml文件没有自动提示问题

    选择打开方式:spring yaml

  4. Head First Servlets & JSP 学习笔记 第十一章 —— Web应用部署

    jar:java archive(java归档) war:web archive(web归档) war文件只是Web应用结构的一个快照,采用了一种更可移植的压缩形式(它实际上就是一个jar文件).建立 ...

  5. win10安装MongoDB提示 the domain,user name and/or password are incorrect. Remember to use "." for the domain if the account is on the local machine.

    好心塞,提示输入不合法. 后来发现这样可以解决.退出安装.重新打开()因为我第一次打开时是没有卡在这一步的,只不过返回上一页时就一直卡在验证的页面了),默认,默认,默认,

  6. squid代理允许FTP访问设置

    # TAG: acl # Defining an Access List ============================= #Default: # acl all src all # #Re ...

  7. 现代编译原理--第六章(中间树 IR Tree 含源码)

    (转载请表明出处   http://www.cnblogs.com/BlackWalnut/p/4559717.html ) 这一章,就虎书而言,理论知识点是及其少的,就介绍了为什么要有一个中间表示树 ...

  8. Python:每日一题003

    题目: 一个整数,它加上100和加上268后都是一个完全平方数,请问该数是多少? 程序分析: 在10000以内判断,将该数加上100后再开方,加上268后再开方,如果开方后的结果满足如下条件,即是结果 ...

  9. 主机性能监控之wmi 获取磁盘信息

    标 题: 主机性能监控之wmi 获取磁盘信息作 者: itdef链 接: http://www.cnblogs.com/itdef/p/3990541.html 欢迎转帖 请保持文本完整并注明出处 仅 ...

  10. 深入理解JVM(二)Java内存区域

    2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...