IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Linux 环境编程 day06 管道通信、XSI进程间通信、消息队列、共享内存、信号量、本地套接字 -> 正文阅读

[网络协议]Linux 环境编程 day06 管道通信、XSI进程间通信、消息队列、共享内存、信号量、本地套接字

Linux 环境编程 day06 管道通信、XSI进程间通信、消息队列、共享内存、信号量、本地套接字

进程通信基本概念

1、什么是进程间通信
    进程间通信(Interprocess communication 也叫IPC):指两个或多个进程之间数据交互的过程。
    为什么进程之间需要通信:进程之间是相互独立的,当它们合作完成一些任务时就需要交互数据。
2、进程间通信的分类
    1、简单的进程间通信
        命令行参数、环境变量、信号、文件
    2、传统的进程间通信:管道
    3、XSI进程间通信:共享内存、消息队列、信号量
    4、基于socket文件的套接字

传统的进程间通信方式-管道

管道是UNIX系统最古老的一种基于文件通信方式,现在已经很少使用,是一种半双工的通信方式。
与普通文件相比的优势就是,当文件内容不存在时,会自动阻塞,不需要调整位置指针。
管道中的数据是流式的,可能出现"粘包"问题,解决方法:
    1、每条数据包中有一个结束标志,常用的标志位有'\n'或'\0',接收者每次只接收1个字节,当遇到结束标志时一个完整的数据包才接收完成,缺点:用户态和内核态之间频繁切换浪费了大量的时间。
    2、规定数据包的大小,发送者与接收者之间约定好数据包的大小,缺点:数据包的大小由最大的数据包决定,如果数据包之间数据量差异比较大,可能会发送大量的垃圾数据。
    3、设置一个包头:
        bytes:123412
        asdfsdflqwerkjlwekrj

有名管道:
    进程A                 进程B
    创建管道文件(mkfifo) ...
    打开管道文件(open)    打开管道文件
    写(read/write)       读
    关闭(close)
    删除(remove)

    int mkfifo(const char *pathname, mode_t mode);
    功能:创建一个管道文件
    pathname:管道文件的路径
    mode:管道文件的权限

匿名管道:
    原理也是基于管道文件,但它没有文件暴露在文件系统中,因此不需要创建也不需要删除,只适合用于父子进程之间。

    int pipe(int pipefd[2]);
    功能:打开一个匿名的管道文件
    pipefd:存储管道文件描述的数组
    注意:下标为0的用于读,下标为1用于写。

    父进程读                 子进程写
    获取管道文件描述符pipe   ...
    创建子进程               会自动拷贝两个文件描述符
    关闭1                    关闭0
    read 0                  write 1
    关闭                      关闭

XSI进程间通信

XSI X/Open System Interface

1、IPC标识符(代表一个用于进程间通信的内核对象)
    使用XSI方式进行进程间通信时,系统会在内核中创建一个内核对象用于通信,然后这个对象会以整数的形式提供给各个进程,类似于文件描述符,是一个非负整数。
    与文件描述符不同的是,从小往大使用,当达到最大值时,向0回转。

2、IPC键值
    用于创建XSI-IPC内核对象的凭证,相当于IPC对象的名字,类似于文件名。
    自定义(类似于文件取名),但是有重名的风险。
    #include <sys/types.h>
    #include <sys/ipc.h>
    key_t ftok(const char *pathname, int proj_id);
    功能:自动生成一个IPC键值
    pathname:当前项目的路径,必须一个真实存在的路径,它靠的路径的位置,而不是字符串。
    proj_id:当前项目的编号
    注意:只要提供相同的路径和项目编号,就可以获得相同的IPC键值。

消息队列

1、基本原理
是由系统内核维护的一个链式队列,每个一条消息由类型、数据、数据长度组成。
和管道类似,但它可以双向通信,还可以按类型接收消息,而不是顺序。
2、常用函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);
功能:创建/获取消息队列
msgflg:
    0   用于获取消息队列
    IPC_CREAT 创建消息队列
    IPC_EXCL  消息队列存在则创建失败
    mode 权限
返回值:成功返回消息队列标识符,失败返回-1

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送数据

msgp:结构指针
    struct msgbuf {
           long mtype;
           char mtext[n];
       };
msgsz:数据的长度,注意不包括消息类型。
msgflg:
    0 当消息队列满时,阻塞
    IPC_NOWAIT 当消息队列满时,不阻塞。
返回值:成功返回0,失败返回-1

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:从消息队列接收数据
msgp:存储数据的空间
msgsz:空间的字节数
msgtyp:要接收的消息类型
    > 0 只接收消息类型等于msgtyp的数据包
    = 0 收消息队列中排名第一的数据包
    < 0 接收第一个消息类型等于<=abs(msgtyp)的数据的包
msgflg:
    0 当消息不存在,阻塞。
    MSG_EXCEPT 接收消息队列中第个类型不是msgtyp的消息
    IPC_NOWAIT 如果接收的消息不存在,立即返回。
返回值:返回收到的字节数

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:销毁/控制消息队列
cmd:
    IPC_STAT    获取消息队列的属性
    IPC_SET     设置消息队列的属性
    IPC_RMID    删除消息队列
buf:消息队列属性结构指针

编程模型:
进程A             进程B
获取key           获取key
创建消息队列      获取消息队列
发送数据          接收数据
接收数据          发送数据
删除

共享内存

1、基本原理
    在内核中开辟一内存,可以让其它进程的虚拟地址与它进行映射,这样就达到多个进程共享同一块内存的目的,当一个进程向这块内存写数据时,其它进了也都可以看到,这样就达到了通信的目的。
    注意:这种通信方式不存在数据的复制,是最快进程间通信方式。
2、常用的函数
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
功能:创建/获取一块内核中共享内存
key:IPC键值(文件名)
size:内存的大小,字节数
shmflg:0表示该参数无效,获取共享内存,size的值也无效。
    IPC_CREAT   创建
    IPC_EXCL    如果存在则创建失败
    mode 权限
返回值:IPC标识符

void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:加载共享内存(把进程中的虚拟地址与内核中的共享内存建立映射关系)
shmid:IPC标识符
shmaddr:虚拟地址,也可以为NULL,操作系统会自动分配。
shmflg:
    SHM_RDONLY 只读
    SHM_RND 当shmaddr为空时,向下整的内存页的整数倍。
返回值:成功返回映射后的虚拟地址,返回返回-1。

int shmdt(const void *shmaddr);
功能:卸载共享内存

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:销毁/控制共享内存
shmid:IPC标识符
cmd:
    IPC_STAT    获取共享内存的属性
    IPC_SET     设置共享内存的属性,uid,gid,mode可以设置。
    IPC_RMID    删除共享内存
    
struct shmid_ds {
    struct ipc_perm shm_perm;   所有都及权限
    size_t shm_segsz;   共享内存的大小,以字节为单位
    time_t shm_atime;   最后加载时间
    time_t shm_dtime;   最后卸载时间
    time_t shm_ctime;   最后修改时间
    pid_t shm_cpid;     创建者的PID
    pid_t shm_lpid;     最后加载/卸载的者PID
    shmatt_t shm_nattch;  加载计数器
};

3、编程模型
进程A         进程B
创建          获取
加载          加载
使用          使用
卸载          卸载
销毁
作业:使用共享内存让进程之间可以对话。

信号量

1、基本原理
    存在于内核中的一个整型变量,相当于计数器,用于限制多个进程对于共享资源的访问。
    当一个资源需要被多个进程共享访问,第一次应该初始化一个该资源有多个份(定义一个信号量并初始化)。
    当有一个进程占用资源时,信号量减1,如果不够减则阻塞。
    当一个进程使用资源完毕后,归还资源,信号量加1,此时之前被阻塞状态的进程将被唤醒。

2、常用函数
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>

    int semget(key_t key, int nsems, int semflg); 
    功能:创建/获取信号量
    nsems:信号的数量,一般为1
    semflg:
        0 获取信号量
        IPC_CREAT 创建信号量
        IPC_EXCL  如果存在则出错
        semflg 权限
    返回值:成功则返回信号量标识符,失败返回-1
    

    int semop(int semid, struct sembuf *sops, unsigned nsops);
    功能:对信号进程加1或减1操作,如果不能减1则阻塞
    sops: 数组
        unsigned short sem_num; 信号量的编号,一般为0
        short          sem_op;  对信号量的操作,
        short          sem_flg;
            0 阻塞
            IPC_NOWAIT 当信号量不能操作时,立即返回,不阻塞。
    nsops:表示sops的数量,数组的长度。
    

    int semtimedop(int semid, struct sembuf *sops, unsigned nsops,struct timespec *timeout);
    功能:对信号进程加1或减1操作,带倒计时的阻塞
    timeout:超时时间

    int semctl(int semid, int semnum, int cmd, 1...);
    功能:销毁/控制信号量
    semnum:信号量的编号
    cmd:
        IPC_STAT 获取信号属性
        IPC_SET 设置信号量属性
        IPC_RMID 删除信号量

        SETVAL 设置信号量的值
        GETVAL 获取信号量的值

编程模型:
    进程A             进程B
    获取key           获取key
    创建信号量        获取信号量
    初始化信号量的值  ...
    操作信号量-1      操作信号量-1
    使用资源...       使用资源...
    操作信号量+1      操作信号量+1
    销毁信号量

本地套接字

1、基本原理
    把网络服务抽象成文件(套接字文件),按照网络通信的格式,进行进程间通信。
2、常用函数
    int socket(int domain, int type, int protocol);
    功能:创建socket对象
    domain:通信方式
        AF_UNIX 本地套按字
        AF_INET 网络通信
    type:数据的发送方式
        SOCK_STREAM 数据流
        SOCK_DGRAM 报文
    protocol:特殊协议,写0即可
    返回值:
        成功返回socket对象描述符
        失败返回-1

    int bind(int sockfd, const struct sockaddr *addr,
            socklen_t addrlen);
    功能:把socket对象与socket文件绑定
    sockfd:socket对象描述符
    addr:socket文件的地址
    addrlen:addr 实际类型的字节数
    struct sockaddr_un
    {
        sa_family_t sun_family; // 与socket函数的domain参数相同即可
        char sun_path[108];     // socket文件的路径
    };

    int listen(int sockfd, int backlog);
    sockfd:socket对象描述符
    功能:开户监听,并设置最大排队数量
    backlog:最大排队数量
    
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    功能:等待对方连接
    sockfd:socket对象描述符
    addr:用于存储对方的通信地址
    addrlen:
        既是输入又是输出,注意。
    返回值:连接成功的socket描述符,可以用它进行读写数据。
    read/write/close函数还可以继续使用。
    
    int connect(int sockfd, const struct sockaddr *addr,
               socklen_t addrlen);
    功能:连接到socket对象
    addr:对方和地址
    addr 实际类型的字节数

编程模型:
    进程A                           进程B
    1、创建socket对象               1、创建socket对象
    2、准备地址(文件的路径)          2、准备地址(文件的路径)
    3、绑定socket对象和socket文件   ...
    4、开启监听                     ...
    5、等待连接                     3、连接
    6、读/写数据                    4、写读数据
    7、关闭socket对象               5、关闭socket对象

查看ipc对象:
ipcs -a 显示所有ipc对象
ipcs -q 显示消息队列
ipcs -m 显示共享内存
ipcs -s 显示信号量

删除ipc对象:
ipcrm -q 删除消息队列
ipcrm -m 删除共享内存
ipcrm -s 删除信号量

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 11:06:18  更:2021-09-08 11:06:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年9日历 -2024/9/23 13:29:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码