进程间通信 (IPC) 方法总结(三)

进程间通信 (IPC) 方法总结(三)

信号量(SEMAPHORE)

信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。
为了获得共享资源,进程需要执行下列操作:

  1. 创建一个信号量:这要求调用者指定初始值,对于二值信号量来说,它通常是1,也可是0。
  2. 等待一个信号量:该操作会测试这个信号量的值,如果小于0,就阻塞。也称为P操作。
  3. 挂出一个信号量:该操作将信号量的值加1,也称为V操作。

为了正确地实现信号量,信号量值的测试及减1操作应当是原子操作。为此,信号量通常是在内核中实现的。Linux环境中,有三种类型:Posix(可移植性操作系统接口)有名信号量(使用Posix IPC名字标识)、Posix基于内存的信号量(存放在共享内存区中)、System V信号量(在内核中维护)。这三种信号量都可用于进程间或线程间的同步。

Posix有名信号量

webp

Posix基于内存的信号量

webp

System V信号量

webp

信号量与普通整型变量的区别

  1. 信号量是非负整型变量,除了初始化之外,它只能通过两个标准原子操作:wait(semap) , signal(semap) ; 来进行访问;
  2. 操作也被成为PV原语(P来源于荷兰语proberen"测试",V来源于荷兰语verhogen"增加",P表示通过的意思,V表示释放的意思),而普通整型变量则可以在任何语句块中被访问;

    信号量与互斥量之间的区别

  3. 互斥量用于线程的互斥,信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。

    互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

    同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。

    在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

  4. 互斥量值只能为0/1,信号量值可以为非负整数。

    也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。

  5. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

套接字(SOCKET)

套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。
套接字示意图

套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。

套接字特性

套接字的特性由3个属性确定,它们分别是:域、端口号、协议类型。

套接字的域

它指定套接字通信中使用的网络介质,最常见的套接字域有两种:

  1. AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。
  2. AF_UNIX,表示UNIX文件系统,它就是文件输入/输出,而它的地址就是文件名。

    套接字的端口号

    每一个基于TCP/IP网络通讯的程序(进程)都被赋予了唯一的端口和端口号,端口是一个信息缓冲区,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数,范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于256的端口号保留给标准应用程序,比如pop3的端口号就是110,每一个套接字都组合进了IP地址、端口,这样形成的整体就可以区别每一个套接字。

    套接字协议类型
  3. 流套接字
    流套接字在域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
  4. 数据报套接字
    它不需要建立连接和维持一个连接,它们在域中通常是通过UDP/IP协议实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并一需要总是要建立和维持一个连接。
  5. 原始套接字
    原始套接字允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW。

原始套接字与标准套接字的区别

原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送数据必须使用原始套接字。

套接字通信的建立

套接字通信的建立

  • 服务端
    1. 首先服务器应用程序用系统调用socket来创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,它不能与其他的进程共享。(socket)
    2. 服务器进程会给套接字起个名字,我们使用系统调用bind来给套接字命名。然后服务器进程就开始等待客户连接到这个套接字。(bind)
    3. 系统调用listen来创建一个队列并将其用于存放来自客户的进入连接。(listen)
    4. 服务器通过系统调用accept来接受客户的连接。它会创建一个与原有的命名套接不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原先的套接字)则被保留下来继续处理来自其他客户的连接(建立客户端和服务端的用于通信的流,进行通信)。(accept--read/write)
  • 客户端
    1. 客户应用程序首先调用socket来创建一个未命名的套接字。(socket)
    2. 将服务器的命名套接字作为一个地址来调用connect与服务器建立连接。(connect)
    3. 一旦连接建立,我们就可以像使用底层的文件描述符那样用套接字来实现双向数据的通信(通过流进行数据传输)(read/write)

eg.

服务端代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //socket listen bind
#include <sys/socket.h>//socket listen bind 
#include <unistd.h>//unlink
#include <sys/un.h>//struct sockaddr_unint main()  
{  /* delete the socket file */  unlink("server_socket");  /* create a socket */  int server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  struct sockaddr_un server_addr;  server_addr.sun_family = AF_UNIX;  strcpy(server_addr.sun_path, "server_socket");  /* bind with the local file */  bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));  /* listen */  listen(server_sockfd, 5);  char ch;  int client_sockfd;  struct sockaddr_un client_addr;  socklen_t len = sizeof(client_addr);  while(1)  {  printf("server waiting:\n");  /* accept a connection */  client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);  /* exchange data */  read(client_sockfd, &ch, 1);  printf("get char from client: %c\n", ch);  ++ch;  write(client_sockfd, &ch, 1);  /* close the socket */  close(client_sockfd);  }  return 0;  
}  

客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //socket listen bind
#include <sys/socket.h>//socket listen bind 
#include <unistd.h>//unlink
#include <sys/un.h>//struct sockaddr_un  int main()  
{  /* create a socket */  int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  struct sockaddr_un address;  address.sun_family = AF_UNIX;  strcpy(address.sun_path, "server_socket");  /* connect to the server */  int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));  if(result == -1)  {  perror("connect failed: ");  exit(1);  }  /* exchange data */  char ch = 'A';  write(sockfd, &ch, 1);  read(sockfd, &ch, 1);  printf("get char from server: %c\n", ch);  /* close the socket */  close(sockfd);  return 0;  
}  

如果我们首先运行tcp_client,会提示没有这个文件:

1335595740_7456.png

因为我们是以AF_UNIX方式进行通信的,这种方式是通过文件来将服务器和客户端连接起来的,因此我们应该先运行tcp_server,创建这个文件,默认情况下,这个文件会创建在当前目录下,并且第一个s表示它是一个socket文件:

1335595745_9357.png

程序运行的结果如下图:

1335595904_8794.png


参考文章:

  1. 进程间通信IPC (InterProcess Communication)

  2. 进程间通信--管道

  3. UNIX/Linux进程间通信IPC系列(四)消息队列

  4. Linux进程间通信(四) - 共享内存

  5. 本地socket通讯

转载于:https://www.cnblogs.com/joker-wz/p/11013086.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode1277. 统计全为 1 的正方形子矩阵(dp)

给你一个 m * n 的矩阵&#xff0c;矩阵中的元素不是 0 就是 1&#xff0c;请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。示例 1&#xff1a;输入&#xff1a;matrix [[0,1,1,1],[1,1,1,1],[0,1,1,1] ] 输出&#xff1a;15 解释&#xff1a; 边长为 1 的正方形有…

实现离线加域---Windows2008 R2 新功能系列之八

我们都知道&#xff0c;部署活动目录&#xff0c;无非搭建一台或多台DC&#xff0c;然后把其它的客户端计算机或成员服务器全部加入域&#xff0c;但在windows2008SP2以前&#xff0c;客户端加入域时&#xff0c;DC必须在线&#xff0c;而从2008R2开始我们已经可以做到让客户端…

【bzoj1263】[SCOI2006]整数划分 高精度

题目描述 从文件中读入一个正整数n&#xff08;10≤n≤31000&#xff09;。要求将n写成若干个正整数之和&#xff0c;并且使这些正整数的乘积最大。 例如&#xff0c;n13&#xff0c;则当n表示为4333&#xff08;或22333&#xff09;时&#xff0c;乘积108为最大。 输入 只有一…

rails i18n模型_Rails国际化的完整指南(i18n)

rails i18n模型by Anastasia由Anastasia Rails国际化的完整指南(i18n) (The Complete Guide to Rails Internationalization (i18n)) In this article you are going to learn how to translate your Rails application into multiple languages, work with translations, loc…

分表后需要注意的二三事

前言 本篇是上一篇《一次分表踩坑实践的探讨》&#xff0c;所以还没看过的朋友建议先看上文。 还是先来简单回顾下上次提到了哪些内容&#xff1a; 分表策略&#xff1a;哈希、时间归档等。分表字段的选择。数据迁移方案。而本篇文章的背景是在我们上线这段时间遇到的一些问题并…

DNS 原理

阮老师的作品&#xff0c;非常精彩&#xff0c;转载&#xff01; DNS 是互联网核心协议之一。不管是上网浏览&#xff0c;还是编程开发&#xff0c;都需要了解一点它的知识。 本文详细介绍DNS的原理&#xff0c;以及如何运用工具软件观察它的运作。我的目标是&#xff0c;读完此…

leetcode1169. 查询无效交易

如果出现下述两种情况&#xff0c;交易 可能无效&#xff1a; 交易金额超过 1000 或者&#xff0c;它和另一个城市中同名的另一笔交易相隔不超过 60 分钟&#xff08;包含 60 分钟整&#xff09; 每个交易字符串 transactions[i] 由一些用逗号分隔的值组成&#xff0c;这些值分…

销售员/学员/讲师系统

前言: 今晚写一篇关于学员/讲师/销售员CRM系统。这个小项目是27号开始做的&#xff0c;大概搞了一星期不到。我把一些知识点总结下&#xff0c;还写下当时克服的BUG。 Django练习小项目&#xff1a;学员管理系统设计开发 带着项目需求学习是最有趣和效率最高的&#xff0c;今天…

Linux内核启动

1 内核编译 解压缩&#xff1a;tar xjf linux-2.6.22.6.tar.bz2打补丁&#xff1a; path -p1 < ../linux-2.6.22.6_jz2440.patch(其中p1是忽略补丁文件中的一级目录)配置&#xff1a; 方法一&#xff1a;使用make menuconfig逐项配置方法二&#xff1a;使用默认配置&#xf…

node.js使用手册_权威的Node.js手册

node.js使用手册Developer and freeCodeCamp camper Flavio Copes has published his entire Node.js Handbook online for free - both on freeCodeCamps Medium publication and as a .pdf file. You can read it here.开发人员和freeCodeCamp营员Flavio Copes在freeCodeCamp…

自动化运维之saltstack(二)states深入理解

深入了解SLS的可以参考这篇博文&#xff1a;http://www.ituring.com.cn/article/42238 个人觉得这篇文章翻译的不错&#xff0c;所以转载过来。 Salt Sates 众多强大而有力的涉及都是建立在简单的原则之上。Salt SLS系统也是努力想K.I.S.S看齐。&#xff08;Keep It Stupidly …

java里面的 |运算符_Java 中 | ^ 运算符的简单使用

背景今天碰到了代码中的按位与运算&#xff0c;复习一下&#xff0c;先列一个各个进制数据表。顺便复习一下十进制转二进制的计算方式&#xff1a;接下来解释下这三个运算符&#xff1a;&  按位与&#xff0c;都转为二进制的情况下&#xff0c;同为1则为1&#xff0c;否则…

leetcode915. 分割数组

给定一个数组 A&#xff0c;将其划分为两个不相交&#xff08;没有公共元素&#xff09;的连续子数组 left 和 right&#xff0c; 使得&#xff1a; left 中的每个元素都小于或等于 right 中的每个元素。 left 和 right 都是非空的。 left 要尽可能小。 在完成这样的分组后返回…

彻底理解正向代理、反向代理、透明代理

套用古龙武侠小说套路来说&#xff0c;代理服务技术是一门很古老的技术&#xff0c;是在互联网早期出现就使用的技术。一般实现代理技术的方式就是在服务器上安装代理服务软件&#xff0c;让其成为一个代理服务器&#xff0c;从而实现代理技术。常用的代理技术分为正向代理、反…

使用showMessageDialog显示消息框

-----------------siwuxie095 工程名&#xff1a;TestJOptionPane 包名&#xff1a;com.siwuxie095.showdialog 类名&#xff1a;TestMessageDialog.java 工程结构目录如下&#xff1a; 代码&#xff1a; package com.siwuxie095.showdialog; import java.awt.BorderLayout;…

将Javascript带到边缘设备

Smart devices today are very similar to labour-saving gadgets a generation ago: Where previously everything got a power cord, now everything gets a chip. 如今的智能设备与上一代的省力小工具非常相似&#xff1a;以前所有设备都配有电源线&#xff0c;而现在所有设…

java 泛型 父子_使用通配符和泛型:完成父子类关系的List对象的类型匹配

泛型和通配符使用泛型和通配符都可以让一个方法所表示的算法逻辑适应多种类型。Java中具备继承关系的类A、B(A extends B)它们的集合List和List之间是没有继承关系的&#xff0c;可以使用泛型或通配符来让一个方法支持同时接受List和List。代码场景这里分别定义类Animal、Dog和…

重定向描述符

文件描符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误 1、重定向错误和数据 1234[rootlogicserver tmp]# ls -al data1 haha 2> qingyun.txt 1&g…

NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证

目录 开发环境  1、建立工程  2、目录结构  3、Express配置文件  4、Ejs模板  5、安装常用库及页面分离  6、路由  7、session  8、页面访问控制及提示JS是脚本语言&#xff0c;脚本语言都需要一个解析器才能运行。对于写在HTML页面里 的JS&#xff0c;浏览器充…

LeetCode-208 Implement Trie (Prefix Tree)

题目描述 Implement a trie with insert, search, and startsWith methods. 题目大意 实现对一棵树的插入、搜索以及前序查找操作。 &#xff08;树的每个节点代表一个小写字母&#xff0c;从根节点到叶节点代表一个完整的单词&#xff09; 示例 E Trie trie new Trie();trie.…