socketpair的理解

article/2025/9/22 11:40:43

参考博客链接:
https://blog.51cto.com/liulixiaoyao/533469

socketpair创建了一对无名的套接字描述符(只能在AF_UNIX域中使用),描述符存储于一个二元数组eg. s[2] 这对套接字可以进行双工通信,每一个描述符既可以读也可以写。
这个在同一个进程中也可以进行通信,向s[0]中写入,就可以从s[1]中读取(只能从s[1]中读取),也可以在s[1]中写入,然后从s[0]中读取;但是,若没有在0端写入,而从1端读取,则1端的读取操作会阻塞,即使在1端写入,也不能从1读取,仍然阻塞;反之亦然…

验证所用代码:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> #define BUF_SIZE 30 int main(){ int s[2]; int w,r; char * string = "This is a test string"; char * buf = (char*)calloc(1 , BUF_SIZE); if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){ printf("create unnamed socket pair failed:%s\n",strerror(errno) ); exit(-1); } /*******test in a single process ********/ if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){ printf("Write socket error:%s\n",strerror(errno)); exit(-1); } /*****read*******/ if( (r = read(s[1], buf , BUF_SIZE )) == -1){ printf("Read from socket error:%s\n",strerror(errno) ); exit(-1); } printf("Read string in same process : %s \n",buf); if( (r = read(s[0], buf , BUF_SIZE )) == -1){ printf("Read from socket s0 error:%s\n",strerror(errno) ); exit(-1); } printf("Read from s0 :%s\n",buf); printf("Test successed\n"); exit(0); 
} 

若fork子进程,然后在服进程关闭一个描述符eg. s[1] ,在子进程中再关闭另一个 eg. s[0] ,则可以实现父子进程之间的双工通信,两端都可读可写;当然,仍然遵守和在同一个进程之间工作的原则,一端写,在另一端读取;

这和pipe有一定的区别,pipe是单工通信,一端要么是读端要么是写端,而socketpair实现了双工套接字,也就没有所谓的读端和写端的区分

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> #define BUF_SIZE 30 int main(){ int s[2]; int w,r; char * string = "This is a test string"; char * buf = (char*)calloc(1 , BUF_SIZE); pid_t pid; if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){ printf("create unnamed socket pair failed:%s\n",strerror(errno) ); exit(-1); } /***********Test : fork but don't close any fd in neither parent nor child process***********/ if( ( pid = fork() ) > 0 ){ printf("Parent process's pid is %d\n",getpid()); close(s[1]); if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){ printf("Write socket error:%s\n",strerror(errno)); exit(-1); } }else if(pid == 0){ printf("Fork child process successed\n"); printf("Child process's pid is :%d\n",getpid()); close(s[0]); }else{ printf("Fork failed:%s\n",strerror(errno)); exit(-1); } /*****read***In parent and child****/ if( (r = read(s[1], buf , BUF_SIZE )) == -1){ printf("Pid %d read from socket error:%s\n",getpid() , strerror(errno) ); exit(-1); } printf("Pid %d read string in same process : %s \n",getpid(),buf); printf("Test successed , %d\n",getpid()); exit(0); 
} 

以上代码中在父子进程之间各关闭了一个描述符,则在父进程写可从子进程读取,反之若子进程写,父进程同样可以读取;大家可以验证下

另外,我也测试了在父子进程中都不close(s[1]),也就是保持两个读端,则父进程能够读到string串,但子进程读取空串,或者子进程先读了数据,父进程阻塞于read操作!

之所以子进程能读取父进程的string,是因为fork时,子进程继承了父进程的文件描述符的,同时也就得到了一个和父进程指向相同文件表项的指针;若父子进程均不关闭读端,因为指向相同的文件表项,这两个进程就有了竞争关系,争相读取这个字符串.父进程read后将数据转到其应用缓冲区,而子进程就得不到了,只有一份数据拷贝(若将父进程阻塞一段时间,则收到数据的就是子进程了,已经得到验证,让父进程sleep(3),子进程获得string,而父进程获取不到而是阻塞)

有网友"笨笨"回复:

“若将父进程阻塞一段时间,则收到数据的就是子进程了,已经得到验证,让父进程sleep(3),子进程获得string,而父进程获取不到”

我验证的情况是,父进程一直阻塞在read上。我想不明白,为什么这时候父进程不能读取数据呢。
而上一种情况,父进程先读取数据,子进程仍然可以读取数据(数据为空),但子进程不会阻塞在read上。

关于这个问题,解释如下:

1.该网友说的情况的确存在,如果先让子进程sleep,此时父进程获得数据,子进程被唤醒之后读到EOF返回;若是让父进程sleep先,子进程先获取数据,之后父进程被唤醒却是一直阻塞不能返回.按理来说这两种情况应该没差别,这个区别下文描述.

2.对于网友提到问题的这个测试,我最初的目的是想说明如果通过产生子进程的方式,对一个写端同时有多个读端,这这些读端之间相互竞争.我们可以用个更有说服力的测试方法来看出这个问题.原来的测试是让一个进程sleep然后另一个进程读完所有字符,可以看到之后醒来的进程就读不到任何字符了.更好的方法是先有一个进程读取一部分的字符,然后第二个进程被唤醒,会发现这第二个进程还能读到一些字符,而这些字符是第一个进程读完剩下的.

3.第一条中的遗留问题,为什么这两种情况有不同的表现.

原因是:如果子进程先sleep,父进程读取完数据之后,父进程退出,此时写端s[0]的引用计数变为0(之前子进程已主动close了一次),被系统释放,根据read的语义,当子进程被唤醒后会读取到EOF;但是当我们先让父进程sleep的时候,子进程读取完后退出,由于写端在父进程,没有被释放,所以父进程此时阻塞在读操作上.

用另外一个测试来证明,我们在子进程中不主动执行close[0],也就是有两个写端,然后其他不变,子进程先sleep,父进程先读取到数据然后退出,但此时更刚刚有个区别,父进程退出的时候s[0]这个写端的描述符并不会减到0,因为子进程中还持有一个引用,所以写端健在,子进程被唤醒之后不会读到EOF返回,而是阻塞在读操作上

最后,有关socketpair在内核中实现的一点点描述:

socketpair会创建两个描述符,但改描述符不属于任何的实际文件系统,而是网络文件系统,虚拟的.同时内核会将这两个描述符彼此设为自己的peer即对端(这里即解决了如何标识读写端,可以想象,两个描述符互为读写缓冲区,即解决了这个问题).然后应用相应socket家族里的read/write函数执行读写操作.

有了这个基础,即可明白为什么试用fork产生的两个子进程都不关闭读端的时候会竞争,如上所述,他们共享相同的文件表项,有相同的inode和偏移量,两个进程的操作当然是相互影响的.


下边这段是我自己的理解:首先因为fork,所以有两对管道,即两个s[0]和两个s[1],s[0]和s[1]都可以做读端或者写端
正常的程序是:父进程关闭s[1],子进程关闭s[0],这样一来,就只剩一对管道,s[0] (父进程) 和s[1](子进程)
父进程往s[0]写入数据,子进程从s[1]中读取数据,没问题。
接下来看博主的测试:
父子进程都不关闭s[1],也就是只有子进程关了一个s[0],剩下两个s[1],一个s[0]
他们所属进程是:父进程拥有s[0],s[1],子进程拥有s[1]
依旧是父进程往s[0]中写入数据,此时有两个读端,即父子进程都有的s[1]。
分两种情况:
子进程先读,而且把数据都读完,那么父进程再读的时候就会阻塞(此时写端s[0]还未关闭)。
而反过来父进程先读,把数据读完之后,父进程退出,关闭自己的s[0],s[1]
此时子进程再读会读到EOF,因为写端已经关闭了。

最后以一个问题结尾:
linux pipe();父进程需要close(fd[0]);子进程close(fd[1]);为什么都需要关闭一个?
在这里插入图片描述
另外找到不错的关于socketpair的博文:
https://blog.csdn.net/weixin_40039738/article/details/81095013


http://chatgpt.dhexx.cn/article/Ox8OmbtC.shtml

相关文章

android socket双向,Android中socketpair双向通信详解

Android很多地方会涉及到进程间的通信&#xff0c;比如输入系统&#xff0c;那么进程间通信会涉及哪些内容呢&#xff1f; 1、进程&#xff1a;负责读取和分发事件 2、应用程序&#xff1a;负责处理输入事件 上面这两个进程会涉及哪些双向通信呢&#xff1a; 1.进程会发送输入事…

Linux下socketpair系统API调用使用说明

目录 1.socketpair函数说明 2.socketpair使用举例 在阅读nginx源码时&#xff0c;发现其调用socketpair来实现master和worker进程之间进行数据交互。其代码如下&#xff1a; 思考&#xff1a;master和worker进程是父子关系&#xff0c;有亲属关系的进程通过pipe/pipe2&#x…

socketpair函数介绍及使用

摘要 在linux下&#xff0c;使用socketpair函数能够创建一对套节字进行进程间通信&#xff08;IPC&#xff09;。 函数原形&#xff1a; #include <sys/types.h> #include <sys/socket.h>int socketpair(int domain, int type, int protocol, int sv[2]); 参数…

socketpair机制

描述 先看下传统的CS模型&#xff0c;如下: 总是一方发起请求&#xff0c;等待另一方回应。当一次传输完成之后&#xff0c;client端发起新的请求之后&#xff0c;server端才作出回应。 那如何才能做到双向通信&#xff1f; 一种解决办法就是client端即使client&#xff0c;又…

【socketpair函数介绍及使用】

socketpair函数介绍及使用 函数原型进程间通信线程间通信 Linux环境下使用socketpair函数创造一对未命名的、相互连接的UNIX域套接字。   管道历史上&#xff0c;它们是半双工的&#xff08;数据只能在一个方向上流动&#xff09;&#xff0c;但是现在也有全双工管道。管道只…

LAMP架构超详细搭建步骤

LAMP介绍&#xff1a; LinuxApacheMysql/MariaDBPerl/PHP/Python一组常用来搭建或者服务器的开源软件&#xff0c;本身都是各自独立的程序&#xff0c;但是因为常被放在一起使用&#xff0c;拥有了越来越高的兼容度&#xff0c;共同组成了一个强大的Web应用程序平台。 目前LA…

LAMP架构介绍

转载自&#xff1a; https://blog.csdn.net/aoli_shuai/article/details/78745984 https://blog.csdn.net/sj349781478/article/details/84224440 一、LAMP介绍&#xff1a; LAMP是 linux Apache MySQL PHP的简写&#xff0c;即把Apache MySQL PHP 安装在linux系统上&#xff…

Lamp架构部署phpmadmin项目

Lamp架构部署phpmadmin项目 文章目录 Lamp架构部署phpmadmin项目官网下载phpmadmin的包测试登陆 官网下载phpmadmin的包 [phpMyAdmin]: 将下载好的包拖入目录里&#xff0c;并解压 [rootlocalhost ~]# cd /usr/src/ [rootlocalhost src]# lsapr-1.6.5 apr-1.6.5.tar.gz a…

【笔记】lamp架构框图

一、lamp架构 (1)、lamp基础结构 (2)、分布式lamp架构 (3)、实际运用 二、OSI七层和TCP/IP五层关系 这部分具体可以参考网址 (1)、OSI七层 OSI&#xff08;Open System Interconnect&#xff09;&#xff0c;即开放式系统互联。 一般都叫OSI参考模型&#xff0c;是ISO&…

LAMP服务架构

LAMP服务架构 文章目录 LAMP服务架构1. LAMP简介2. LAMP工作原理3. 部署LAMP3.1 源码安装http服务3.2 源码安装mysql数据库3.3 源码安装php3.2 apache和php配置 1. LAMP简介 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写 L代表服务器操作系统使用…

LAMP架构部署论坛

搭建论坛&#xff0c;要求为8080端口 安装LAMP 架构所需的服务&#xff0c;部分及插件 yum -y install mariadb mariadb-server mariadb-libs php php-mysql php-gd php-fpm php-cli gd httpd 启动服务&#xff1a;systemctl start httpd mariadb 设置数据库密码&#xff1a…

快速搭建LAMP架构

快速搭建LAMP架构 1.安装apache2.部署mysql3.部署php结合apache4.验证5.部署一个论坛disuz 1.安装apache [rootlocalhost ~]# yum install httpd -y 已加载插件&#xff1a;fastestmirror, langpacks Loading mirror speeds from cached hostfile* base: mirrors.aliyun.com* …

LAMP架构简介与配置

文章目录 前言LAMP 简介与概述LAMP平台概述 构建LAMP平台顺序编译安装的优点各组件的主要作用 编译安装 Apache编译安装mysql安装PHP 前言 LAMP 简介与概述 LAMP平台概述 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整台系统和相关软件&#x…

搭建LAMP架构

搭建LAMP架构 一、LAMP架构概述 1、LAMP简介 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整台系统和相关软件&#xff0c;能够提供动态web站点服务及其应用开发环境。 LAMP是一个缩写词&#xff0c;具体包括Linux操作系统&#xff0c;Apache网…

LAMP架构简介与概述 及服务安装

目录 1、LAMP平台概述 &#xff08;1&#xff09;LAMP平台概述 &#xff08;2&#xff09;构建LAMP平台顺序 &#xff08;3&#xff09;编译安装的优点 &#xff08;4&#xff09;各组件的主要作用 2、Apache概述 &#xff08;1&#xff09; 安装Apache服务&#xff1a;…

什么是LAMP架构?

LAMP架构介绍 LAMP动态网站架构 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写。 1、LAMP分别代表什么&#xff1f; L代表服务器操作系统使用Linux A代表网站服务使用的是Apache软件基金会中的httpd软件 M代表网站后台使用的数据库是MySQL数…

【ubuntu】搭建lamp架构

文章目录 一、准备工作1、更新源2、更新软件3、防火墙UFW 二、安装apache21、安装apache包2、网页浏览查看 三、安装mysql1、安装mysql2、查看mysql3、设置mysql数据库的密码 四、安装PHP1、安装php包以及插件2、测试php包 五、安装wordpress1、获取wordpress的压缩包2、上传压…

腾讯云— LAMP 架构个人实践分享

LAMP 环境通常指Linux 环境下&#xff0c;由ApacheMySQL/MariaDBPHP 以及其它相关组件组成的网站服务器架构。目前以LAMP组成的Web 应用程序平台广泛被应用&#xff0c;70%以上的访问流量由LAMP提供&#xff0c;所以我们也认同LAMP是最强大的网站解决方案。 关于LAMP的环境部署…

一:LAMP 架构简介

一&#xff1a;LAMP 架构简介 LAMP 是目前成熟的一种企业网站应用模式之一&#xff0c;指的是协同工作的一套系统和相关软件的整合&#xff0c;可提供PHP动态web站点应用及开发环境&#xff0c;LAMP 经过十年的完善各个组件间的兼容性&#xff0c;协作能力&#xff0c;稳定等方…

php lamp架构,lamp架构搭建

lamp架构搭建(yum) 环境&#xff1a;一台主机&#xff0c;centos7.5 lamp安装 yum -y install httpd php-fpm php-mysql mariadb-server 启动php-fpm服务 systemctl start php-fpm 配置httpd生成配置文件&#xff0c;提示http&#xff0c;php-fpm服务在本地 vim /etc/httpd/con…