当前位置: 首页 > 编程日记 > 正文

Linux网络编程--进程间通信(一)

进程间通信简介(摘自《Linux网络编程》p85)

AT&T 在 UNIX System V 中引入了几种新的进程通讯方式,即消息队列( MessageQueues),信号量( semaphores)和共享内存( shared memory),统称为 System V IPC。在Linux 系统编程中,它们有着广泛的应用。
  System V IPC 的一个显著的特点,是它的具体实例在内核中是以对象的形式出现的,我们称之为 IPC 对象。每个 IPC 对象在系统内核中都有一个唯一的标识符。通过标识符内核可以正确的引用指定的 IPC 对象.。需要注意的是,标识符的唯一性只在每一类的 IPC 对象内成立。比如说,一个消息队列和一个信号量的标识符可能是相同的,但绝对不会出现两个有相同标识符的消息队列。

标识符只在内核中使用, IPC 对象在程序中是通过关键字( key)来访问的。和 IPC 对象标识符一样,关键字也必须是唯一的。而且,要访问同一个 IPC 对象, Server 和 Client必须使用同一个关键字。因此,如何构造新的关键字使之不和已有的关键字冲突,并保证Server 和 Client 使用的关键字是相同的,是建立 IPC 对象时首先要解决的一个问题。(具体在后边的msg通信中详解)

通信方法还有:半双工管道pipe,命名管道fifo,消息队列,信号量,共享内,socket套接字等,下面一一介绍:

半双工管道:

int pipe(int filedes[2]);

管道是将两个进程之间的标准输入输出相互对接的机制

linux命令中使用的管道 |  : ls -l | grep *.c  //显示文件(输入端)-(|)-(输出端)>找到.c结尾文件

实现:因为半双工缘故,所以只能实现一段输入,一段输出,而不能双向通信。所以:实现为,通过管道连接进程,一端开放读文件描述,一端开放写文件描述

//管道的性质就是,一个进程的输出作为另一个进程的输入
//那么我们可以关闭一个进程读端使之作为输入端,
//另一个进程关闭写端,读取数据,接收数据作为管道输出端//FIFO命名管道
//文件系统中,命名管道是特殊文件的方式存在的
//不同进程可以通过命名管道共享数据//命名管道一直是阻塞方式的,且必须是显示的通过open建立连接到管道的通道
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>#include<sys/types.h>int main()
{int result = 1;int fd[2];pid_t pid;int *write_fd = &fd[1];        //写文件描述int *read_fd = &fd[0];        //读文件描述int nbytes;char str[] = "管道,你好\n";    char readBuffer[80];memset(readBuffer,0,sizeof(readBuffer));result = pipe(fd);        //创建管道if(-1==result){printf("管道创建失败!\n");return -1;}pid = fork();            //进程创建分叉程序if(-1 == pid){printf("fork失败");return -1;}if(0==pid)            //子进程关闭读端,写入字符
    {close(*read_fd);result = write(*write_fd,str,strlen(str));printf("写入%d个数据\n",result);}else                //父进程关闭写端,读取数据
    {close(*write_fd);nbytes = read(*read_fd,readBuffer,sizeof(readBuffer));printf("接收到%d个数据,内容为%s",nbytes,readBuffer);}return 0;
}

②命名管道

int mkfifo(const char* pathname,mode_t mode);

类似于普通管道,只是

a.在文件系统中以设备特殊文件的形式存在

b.不同进程之间可以通过命名管道共享数据

操作区别于普通管道:FIFO中必须显式通过open建立连接到管道的通道,且总是处于阻塞状态的

消息队列

  消息队列是内核地址空间的内部链表,通过内核在各个进程之间传递内容。每个消息队列通过唯一IPC标识符标识,不同队列相对独立。

  

//file: msg.h
/*
message buffer for msgsnd and msgrcv calls */ struct msgbuf {__kernel_long_t mtype; /* type of message */char mtext[1]; /* message text */ };/* Obsolete, used only for backwards compatibility and libc5 compiles */ struct msqid_ds {struct ipc_perm msg_perm;struct msg *msg_first; /* first message on queue,unused */struct msg *msg_last; /* last message in queue,unused */__kernel_time_t msg_stime; /* last msgsnd time */__kernel_time_t msg_rtime; /* last msgrcv time */__kernel_time_t msg_ctime; /* last change time */unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */unsigned long msg_lqbytes; /* ditto */unsigned short msg_cbytes; /* current number of bytes on queue */unsigned short msg_qnum; /* number of messages in queue */unsigned short msg_qbytes; /* max number of bytes on queue */__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */__kernel_ipc_pid_t msg_lrpid; /* last receive pid */ };
//filename
/*
Obsolete, used only for backwards compatibility and libc5 compiles */ struct ipc_perm {__kernel_key_t key;  //函数msgget()使用的键值  __kernel_uid_t uid;  //用户UID__kernel_gid_t gid;  //用户GID__kernel_uid_t cuid;  //创建者UID__kernel_gid_t cgid;  //创建者GID__kernel_mode_t mode;   //权限unsigned short seq;  //序列号 };

内核中的消息队列

注:结构list_head 形成一个链表,结构msg_msg之中的m_list使得消息形成链表,查找,插入时,对m_list域进行偏移找到位置

相关函数:

键值构建 key_t ftok(const char* pathname,int proj_id);

获取消息 int msgget(key_t key,int msgflg);

发送消息 int msgsnd(int msqid, const void * msgp,size_t msgsz,int msgflg);

接收消息 ssize_t msgrcv(int msqid, void * msgp, size_t msgsz, long msgtype, int msgflg);

消息控制 int msgctl(int msqid, int cmd, struct msqid_ds *buf);  //向内核发送cmd命令判断进行何种操作

一个简单例子

④信号量

信号量是一种计数器,用来控制对多个进程共享的资源所进行的访问。常用作锁机制(生产者消费者模型是个典型使用)

信号量结构

//filename sys/sem.h
/*
arg for semctl system calls. */ union semun {int val; /* value for SETVAL */struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */unsigned short *array; /* 数组结构 */struct seminfo *__buf; /* 信号量内部结构 */void *__pad; };

相关函数

新建信号量 int semget(key_t key, int nsems, int semflg);

//key 来自于ftok()

信号量操作函数 int semop(int semid,struct sembuf* sops, unsigned nsops);

//信号量的P,V操作通过向已经建立好的信号量发送命令完成

控制信号量参数

int semctl(int semid, int semnum ,int cmd,.....);

//用于在信号量集合上执行控制操作

#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h>typedef int sem_t;
union semun
{int val;struct semid_ds * buf;unsigned short *array;
}arg;sem_t CreateSem(key_t key, int value)
{union semun sem;sem_t semid;sem.val = value;semid = semget(key,0,IPC_CREAT);if(-1 == semid){printf("create semaphore error\n");return -1;}semctl(semid,0,SETVAL,sem);return semid;
}int Sem_P(sem_t semid)
{
struct sembuf sops = {0,+1,IPC_NOWAIT};
return (semop(semid,&sops,1));
}int Sem_V(sem_t semid)
{struct sembuf sops = {0,-1,IPC_NOWAIT};return (semop(semid,&sops,1));
}void SetvalueSem(sem_t semid , int value)
{union semun sem;sem.val = value;semctl(semid,0,SETVAL,sem);
}int GetvalueSem(sem_t semid)
{union semun sem;return semctl(semid,0,GETVAL,sem);
}void DestroySem(sem_t semid)
{union semun sem;sem.val = 0;semctl(semid,0,IPC_RMID,sem);
}
int main()
{key_t key;int semid;char i;int value = 0;key = ftok("/ipc/sem",'a');semid = CreateSem(key,100);for( i = 0;i <= 3;++i){Sem_P(semid);Sem_V(semid);    }value = GetvalueSem(semid);    DestroySem(semid);    return 0;
}

⑤共享内存(最快捷的方法)没有中间过程,管道等

在多个进程之间共享内存区域的一种进程间通信方式,在多个进程之间对内存段进行映射的方式实现内存共享。

    相关函数

  创建共享内存函数 int shmget(key_y key, size_t size, int shmflg);

  获得共享内存地址void * shmat(int shmid,const void* shmaddr, int shmflg);

  删除共享内存函数 int shmdt(const void* shmadddr);

  共享内存控制函数 int shmctl(int shmid ,int cmd, struct shmid_ds * buf);

⑥信号

用于在一个或多个进程之间传递异步信号。

相关函数

信号截取 sighandler signal(int signum ,sighandler handler);

发送信号 int kill(pid_t pid, int sig);

int raise(int sig);

  

  

转载于:https://www.cnblogs.com/lang5230/p/5502771.html

相关文章:

mysql 行号_PQ获取TABLE的单一值作为条件查询MySQL返回数据

下午&#xff0c;我正爽歪歪地喝着咖啡&#xff0c;看着Power BI每秒钟刷新一次&#xff0c;静静等待某个分公司完成本月绩效任务&#xff0c;自动调用Python在钉钉群中发送喜报&#xff1a;紧接着再次调用Python将Power BI云端报告中的各分公司最新完成率数据和柱状图截图发在…

UUID的使用及其原理

今天敲项目要用UUID&#xff0c;想起之前老师告诉UUID的使用&#xff0c;但没说具体的生成逻辑&#xff0c;于是我进行了百度 首先&#xff0c;UUID的使用&#xff1a; //生成随机的UUID String uuid UUID.randomUUID().toString().replaceAll("-", "")…

链表类型题目需要用到的头文件list.h

下面是后面链表相关题目中需要用到的链表结点的定义和相关操作函数&#xff0c;参见下面的list.h文件&#xff1a; 注意链表结点的定义采用cpp的定义方式&#xff0c;它会被cpp的文件调用。比如后面删除链表重复结点的文件del_repeated_list.cpp中的编译方式&#xff1a; g -…

led计数电路实验报告_「正点原子FPGA连载」第八章 按键控制LED灯实验

1)实验平台&#xff1a;正点原子开拓者FPGA开发板2)本实例源码下载&#xff1a;请移步正点原子官网第八章 按键控制LED灯实验按键是常用的一种控制器件。生活中我们可以见到各种形式的按键&#xff0c;由于其结构简单&#xff0c;成本低廉等特点&#xff0c;在家电、数码产品、…

svn官方备份hot-backup.py强烈推荐

Author:牛班图 Date:2016/05/18 Address:suzhou --- centos 6.7默认安装的python是2.6.6&#xff0c;大家可以先查看一下自己操作系统的python版本&#xff0c;python -v&#xff1b; hot-backup.py是基于python2写的&#xff0c;python3的语法有些地方不一样&#xff0c;所以在…

用js方法做提交表单的校验

基础知识&#xff1a; 原始提交如下&#xff1a; <form action"<%basePath %>puser/register" method"post"><input placeholder"Name" name"realname"> <input type"email" placeholder"Email…

tree类型题目需要用到的头文件tree.h

下面是树类型题目需要用到的头文件tree.h,请包含在cpp文件中编译,而不是放在c文件中编译,比如查找树中两个节点的最低公共父结点的题common_parent_in_tree.cpp,编译它的方法是: g -g common_parent_in_tree.cpp -o common_parent_in_tree 下面是tree.h的内容: #include <…

用easyui动态创建一个对话框

function randomString(len) { len len || 32; var $chars ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/ var maxPos $chars.length; var pwd ; for (i 0; i < len; i) { pwd $…

网站收录工具(php导航自动收录源码)_网站如何快速收录,网站不收录怎么办?...

经常有朋友说怎么快速收录&#xff0c;网站不收录怎么收录&#xff1f;&#xff1f;其实&#xff0c;网站不包括一般的新网站数量&#xff0c;没有SEO基础&#xff0c;SEO了解合作伙伴经常会遇到问题&#xff0c;甚至很多人会告诉你&#xff0c;不包括网站引流&#xff0c;导致…

JS Uncaught SyntaxError:Unexpected identifier异常报错原因及其解决方法

最近在写ajax的时候&#xff0c;调用js方法&#xff0c;遇到了Uncaught SyntaxError:Unexpected identifier异常报错&#xff0c;开始搞不清原因&#xff0c;很苦恼。 以为是js方法参数个数和长度的问题&#xff0c;后来发现原来是这样~ 以下是 浏览器窗口的报错 以及 按钮处…

python 打印皮卡丘_Python到底是什么?学姐靠它拿了5个offer

你ZAO吗&#xff1f;最近陌陌发布了一款很有意思的产品——ZAO&#xff0c;这款AI换脸的产品刷爆朋友圈&#xff01;这款产品火爆到什么程度呢&#xff1f;正在使用ZAO的用户会发现&#xff0c;想要生成一段新的AI换脸视频&#xff0c;已经不是等待几秒、排队第几位的问题&…

有一个1亿结点的树,已知两个结点, 求它们的最低公共祖先!

对该问题,分为如下几种情形讨论: 情形一: 假如该树为二叉树,并且是二叉搜索树, 依据二叉搜索树是排过序的, 我们只需要从树的根结点开始,逐级往下,和两个输入的结点进行比较. 如果当前结点的值比两个结点的值都大,那么最低的公共祖先一定在当前结点的左子树中,下一步遍历当前…

数据库SQL优化大总结之百万级数据库优化方案

1.对查询进行优化&#xff0c;要尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中对字段进行 null 值判断&#xff0c;否则将导致引擎放弃使用索引而进行全表扫描&#xff0c;如&#xff1a; select id from t w…

js定时执行函数

方法一: //直接现定义函数 var time window.setInterval(function(){ $(’.lingdao_right’).click(); },5000); 方法二: //执行已经有的函数 var time window.setInterval(‘abc()’,5000); 清除js自动执行 clearInterval(time); //time就是定义时的名称&#xff0c;如上

BST(binary search tree)类型题目需要用到的头文件binary_tree.h

下面是二叉搜索树需要用到的头文件binary_tree.h #include <stdio.h>struct BinaryTreeNode{int value;BinaryTreeNode* pLeft;BinaryTreeNode* pRight; };BinaryTreeNode* CreateBinaryTreeNode(int value){BinaryTreeNode* pNode new BinaryTreeNode();pNode->valu…

终止js程序执行的方法

js终止程序执行的方法共有三种 (一)在function里面&#xff08;普通js方法&#xff09; &#xff08;1&#xff09;return; &#xff08;2&#xff09;return false; (二)非function方法里面&#xff08;如ajax方法&#xff09; alert(“发生异常”); throw SyntaxError(); ale…

将BST转换为有序的双向链表!

在二叉树中,每个结点都有两个指向子结点的指针. 在双向链表中, 每个结点也有两个指针,它们分别指向前一个结点和后一个结点.由于这两种结构的相似性, 同时二叉搜索树也是一种排过序的数据结构, 因此在理论上有可能实现二叉搜索树和排序的双向链表之间的转换. 下面的文件BST_to_…

计算机病毒实践汇总五:搭建虚拟网络环境

在尝试学习分析的过程中&#xff0c;判断结论不一定准确&#xff0c;只是一些我自己的思考和探索。敬请批评指正&#xff01; 涉及内容&#xff1a; INetSim安装及使用 ApateDNS安装及使用 1. 搭建病毒分析网络环境原因 使用虚拟机作为沙箱能把病毒与外界完全隔离开&#xff0c…

form表单提交前进行ajax或js验证,校验不通过不提交

在使用form表单进行提交数据前&#xff0c;需要进行数据的校验->表单的校验&#xff08;如&#xff1a;两次密码输入是否相同&#xff09;后台数据的校验&#xff08;如&#xff1a;账号是否存在&#xff09;&#xff0c;这个时候&#xff0c;如果哪步校验不通过&#xff0c…

中体骏彩C++面试题

下面是我凭记忆想到的几个题目,有需要的同学就拿去吧,我也算做了点善事. 中体骏彩C笔试题 2013-11-18 1.指针的含义是:B A.名字 B.地址 C.名称 D.符号 2.给出下面的程序输出: #include <iostream> #include <cstdlib> #include <cstring> #include <l…

Fibonacci数列的java实现

关于Fibonacci应该都比较熟悉&#xff0c;0,1,1,2,3.。。。。 基本公式为f(n) f(n-1) f(n-2); f(0) 0; f(1) 1; 方法1&#xff1a;可以运用迭代的方法实现&#xff1a; public static int f1(int n){if(n<1)return n;return f1(n-1) f1(n-2); }实现方法简单。 方法2&am…

stream流对象的理解及使用

我的理解&#xff1a;用stream流式处理数据&#xff0c;将数据用一个一个方法去 . &#xff08;点&#xff0c;即调用&#xff09; 得到新的数据结果&#xff0c;可以一步达成。 有多种方式生成 Stream Source&#xff1a; 从 Collection 和数组 Collection.stream()Collecti…

永成科技C++笔试题

最后几个题有点难度,在这里说一下: 永成科技C笔试题 2013-11-19 1.将1亿以内的质数存到一个超级大的数组中,用算法如何实现? 使用"筛法"求解1亿以内的质数的程序的思路: 先动态分配1亿个bit(总计12500000字节),用字节中的每一位代表每一个整数,首先将代表奇数的那…

事务库事务隔离级别

为了快速同步数据的需要&#xff0c;我分段执行了两次python脚本&#xff0c;即开启了两个进程同步数据&#xff0c;结果服务器不时报出数据库死锁异常&#xff0c;通过排查代码和数据库日志发现&#xff0c;是由长事务并发引起的。代码中有入账和出账两个方法&#xff0c;里面…

十大算法,描述+代码+演示+分析+改进(赶紧收藏!)

十大算法 1.冒泡排序 ​ &#xff08;1&#xff09;算法描述 ​ 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是…

webkit入门准备

《webkit入门准备》1. Ca) Webkit代码风格b) Inlinec) Constd) 构造与析构e) 重载f) 继承2. 泛式编程a) Vector/List/HashTableb) Iteratorc) 智能指针3. 面向对象编程a) 对象概念b) …

oracle操作

一、导入dmp文件&#xff1a; 1.创建表空间create tablespace 表空间 datafile 路径\文件名.dbf size 1500M autoextend on next 5M maxsize 3000M;注&#xff1a;路径必须为已创建2.创建用户create user 用户名 identified by 密码 default tablespace 表空间;3.更改用户的表空…

一个form表单,多个提交按钮(实现不同功能和地址的提交)

直接上代码 表单部分&#xff1a; <form action"" name"find" method"post" enctype"multipart/form-data"><input type"text" name"name"/><br/><button οnclick"f1()"/>找…

chrome 硬件渲染(GPU Accelerated Compositing in Chrome)

原文链接 http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome chrome 中集成了webkit,这篇文章对webkit 硬件渲染过程有详细的介绍&#xff0c;很好。 简介 这篇文档讲解chrome硬件加速合成的实现细节和背景。 介绍 通常来讲&#…

CCS Font 知识整理总结

总是搞不懂 CCS 中如何正确的使用字体&#xff0c;这下明白了。 1、什么是 font-face font-face 顾名思义&#xff0c;就是文字的脸。字体是文字的外在形式&#xff0c;就是文字的风格&#xff0c;是文字的外衣。比如行书、楷书、草书&#xff0c;都是一种字体。同样一个字每个…