栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

进程间通信

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

进程间通信

一、命名管道FIFO

FIFO IPC机制:利用文件系统中系统文件来标识的。可以用mkfifo命令创建一个FIFO文件:

mkfifo tube

ls -l tube

FIFO文件在磁盘上没有数据块,仅用来标识内核中的一条通道,各进程可以打开这个文件进行read/write,实际上是在读写内核通道(根本原来在于file结构体所指向的read,write函数和常规文件不一样),就实现了进程间通信。

二、共享内存 1.共享存储

允许两个或多个进程共享一给定的存储区。因为数据不需要再客户机和服务器之间复制。

2.调用第一个函数是shmget,获得一个指定大小的共享存储标识符。

①key:用来标识共享内存size参数该共享存储段最小值,如果正在创建一个新段,必须指定size。如果正在存放一个现存的段,将size指定为0。

②shmflg:IPC_CREATE和IPC_EXCL,最为重要的是shmflg中指明访问权限,跟open的mode参数一样。否则出现permission denied错误。

③返回:若成功则为共享内存ID,出错则为-1。

④key由ftok()生成。pathname必须为调用进程可以访问的。pathname和proj_id共同组成一个key。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


int main(void) {
    key_t key = ftok("./9_1readfifo.c", 9);
    if (key < 0) {
        perror("ftok");
        exit(1);
    }
    printf("key=0x%xn", key);

    int shmid = shmget(key, 20, IPC_CREAT  | 0666);
    if (shmid < 0) {
        perror("shmget");
        exit(1);
    }
    printf("shmid=%dn", key);
    return 0;
}

3.调用一旦创建一个共享存储段,进程就可调用shmat将其连接到它的地址空间中。

①返回:若成功则为指向共享存储段的指针,出错则为-1.

②共享存储段连接到调用进程的哪个地址上与addr参数以及flag中是否指定SHM_RND位有关:

如果addr=NULL:此段连接到由内核选择的第一个可用地址上。

如果addr非NULL,并没有指定SHM_RND:此段连接到addr指定的地址上。

如果addr非0,并且指定SHM_RND:此段连接到addr-(addr mod SHMLBA)表示的地址上。

SHM_RND:取整。

SHM_LBA:低边界地址倍数,总是2的乘方。

该算式将地址向下取最近1个SHMLBA的倍数。

③一般指定addr=0,以便由内核选择地址。

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


int main(void) {
    key_t key = ftok("./9_1readfifo.c", 9);
    if (key < 0) {
        perror("ftok");
        exit(1);
    }
    printf("key=0x%xn", key);

    int shmid = shmget(key, 20, IPC_CREAT  | 0666);
    if (shmid < 0) {
        perror("shmget");
        exit(1);
    }
    printf("shmid=%dn", key);

    void *shmp = shmat(shmid, NULL, 0);
    if (shmp < 0) {
        perror("shmat");
        exit(1);
    }
    printf("shmp=%pn", shmp);
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(1);
    }
    if (pid) {
        //parent process
        while (1) {
            scanf("%s", shmp);
            if (!strcmp(shmp, "quit")) break;
        }
        wait(NULL);
    } else {
        //child process
        while (1) {
            if (!strcmp(shmp, "quit")) break;
            if (shmp) {
                printf("child read %sn", shmp);
                bzero(shmp, 20);
            }
            sleep(1);
        }
    }
    shmdt(shmp);
    return 0;
}

 

4.调用当对共享存储段的操作已经结束时,则调用shmdt脱接该段。

(并不从系统中删除其标识符以及其数据结构。该标识符依然存在直到某个进程调用shmctl带命令IPC_RMID特地删除它)

shmaddr参数:以前调用shmat时返回值:返回成功为0,错误为-1.

5.调用shmctl对共享存储段执行多种操作

三、消息队列

1.系统内核维护一个存放消息的队列,不同用户可以向队列中发送信息或者队列中接收消息。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main() {
    key_t key = ftok("./tube", 9);
    printf("mqid=%#xn", key);
    int mqid = msgget(key, IPC_CREAT | 0666);
    printf("mqid=%dn", mqid);
    return 0;
}
2.往队列里发送一条消息。此操作被中断后不会被重启(信号处理中SA_RESTART)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MSGLEN 20

typedef struct msgbuf
{
    long mtype;
    char mtext[MSGLEN];
}MSG;


int main() {
    key_t key = ftok("./tube", 9);
    printf("mqid=%#xn", key);
    int mqid = msgget(key, IPC_CREAT | 0666);
    printf("mqid=%dn", mqid);

    MSG msg;
    msg.mtype = 1;
    strncpy(msg.mtext, "how are you?n", MSGLEN);
    msgsnd(mqid, &msg, MSGLEN, 0);

    msg.mtype = 2;
    strncpy(msg.mtext, "hahan", MSGLEN);
    msgsnd(mqid, &msg, MSGLEN, 0);
    return 0;
}

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MSGLEN 20

typedef struct msgbuf
{
    long mtype;
    char mtext[MSGLEN];
}MSG;


int main() {
    key_t key = ftok("./tube", 9);
    printf("mqid=%#xn", key);
    int mqid = msgget(key, IPC_CREAT | 0666);
    printf("mqid=%dn", mqid);

    MSG msg;
    msgrcv(mqid, &msg, MSGLEN, 2, 0);
    printf("msg.type=%ldnmsg,text=%sn", msg.mtype, msg.mtext);

    msgrcv(mqid, &msg, MSGLEN, 1, 0);
    printf("msg.type=%ldnmsg,text=%sn", msg.mtype, msg.mtext);
    return 0;
}

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/729574.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号