进程间通信(IPC)的方法:UNIX域套接字

      UNIX域套接字(UNIX domain socket)为我们提供了一种在进程之间建立通信通道的便捷方法,具有许多有用的内置功能。它支持面向流(TCP)和面向数据报(UDP)协议作为TCP/IP互联网套接字。我们还可以在阻塞和非阻塞模式之间进行选择。
      首先需要创建套接字并在套接字函数中指定AF_UNIX作为域套接字。创建套接字后,必须使用绑定函数将套接字绑定到唯一的文件路径。与AF_INET域中的Internet套接字绑定到唯一的IP地址和端口号不同,UNIX域套接字绑定到文件路径。文件系统中创建的此文件,当程序关闭且不再需要该文件时,你必须手动将其删除。
      UNIX域套接字与server/client网络套接字通信没有太大不同,但它旨在供本地文件系统使用。server/client网络套接字介绍参考:https://blog.csdn.net/fengbingchun/article/details/107848160

      UNIX域套接字总结
      (1).同步;
      (2).极高的吞吐量;存储设备速度限制;
      (3).双向通信;
      (4).以线性方式读写;
      (5).自动内存管理。

      注:以上内容主要来自网络整理。

      测试代码如下:

#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <iostream>int main()
{// reference: https://biendltb.github.io/tech/inter-process-communication-ipc-in-cpp/const char* server_sock_path = "/tmp/unix_sock.server";const char* client_sock_path = "/tmp/unix_sock.client";pid_t pid = fork(); // create two processes of client and serverif (pid < 0) {fprintf(stderr, "fail to fork\n");return -1;}if (pid != 0) { // server process(parent process)auto server_sock = socket(AF_UNIX, SOCK_STREAM, 0); // open the server socket with the SOCK_STREAM typeif (server_sock == -1) {fprintf(stderr, "SERVER: fail to socket: %s\n", strerror(errno));exit(1);}// bind to an address on file system// similar to other IPC methods, domain socket needs to bind to a file system, so that client know the address of the server to connect tostruct sockaddr_un server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sun_family = AF_UNIX;strcpy(server_addr.sun_path, server_sock_path);unlink(server_sock_path); // unlink the file before bind, unless it can't bind: error info: Address already in useauto rc = bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));if (rc == -1) {fprintf(stderr, "SERVER: fail to bind: %s\n", strerror(errno));exit(1);}// listen and accept client connection// set the server in the "listen" mode and maximum pending connected clients in queuerc = listen(server_sock, 10);if (rc == -1) {fprintf(stderr, "SERVER: fail to listen: %s\n", strerror(errno));exit(1);}fprintf(stdout, "SERVER: Socket listening...\n");struct sockaddr_un client_addr;auto len = sizeof(client_addr);int client_fd = accept(server_sock, (struct sockaddr *)&client_addr, (socklen_t*)&len);if (client_fd == -1) {fprintf(stderr, "SERVER: fail to accept: %s\n", strerror(errno));exit(1);}fprintf(stdout, "SERVER: Connected to client at: %s\n", client_addr.sun_path);fprintf(stdout, "SERVER: Wating for message...\n");const int buf_len = 256;char buf[buf_len];memset(buf, 0, buf_len);int byte_recv = recv(client_fd, buf, buf_len, 0);if (byte_recv == -1) {fprintf(stderr, "SERVER: fail to recv: %s\n", strerror(errno));exit(1);}elsefprintf(stdout, "SERVER: Server received message: %s.\n", buf);fprintf(stdout, "SERVER: Respond to the client...\n");memset(buf, 0, buf_len);strcpy(buf, "hello from server");rc = send(client_fd, buf, buf_len, 0);if (rc == -1) {fprintf(stderr, "SERVER: fail to send:%s\n", strerror(errno));exit(1);}fprintf(stdout, "SERVER: Done!\n");close(server_sock);close(client_fd);remove(server_sock_path); // remove access to a file namedint status;auto pid2 = wait(&status); // system call suspends execution of the calling thread until one of its children terminatesfprintf(stdout, "process ID of the terminated child: %d\n", pid2);if (WIFEXITED(status)) { // returns true if the child terminated normallyfprintf(stdout, "child process ended with: exit(%d)\n", WEXITSTATUS(status));}if (WIFSIGNALED(status)) { // returns true if the child process was terminated by a signalfprintf(stderr, "child process ended with: kill -%d\n", WTERMSIG(status));}}if (pid == 0) { // client process(child process)int client_sock = socket(AF_UNIX, SOCK_STREAM, 0);if (client_sock == -1) {fprintf(stderr, "CLIENT: fail to socket: %s\n", strerror(errno));exit(1);}// bind client to an address on file system// Note: this binding could be skip if we want only send data to server without receivingstruct sockaddr_un client_addr;memset(&client_addr, 0, sizeof(client_addr));client_addr.sun_family = AF_UNIX;strcpy(client_addr.sun_path, client_sock_path);unlink (client_sock_path);auto rc = bind(client_sock, (struct sockaddr *)&client_addr, sizeof(client_addr));if (rc == -1) {fprintf(stderr, "CLIENT: fail to bind: %s\n", strerror(errno));exit(1);}// Set server address and connect to itstruct sockaddr_un server_addr;server_addr.sun_family = AF_UNIX;strcpy(server_addr.sun_path, server_sock_path);rc = connect(client_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));if (rc == -1) {fprintf(stderr, "CLIENT: fail to connect: %s\n", strerror(errno));exit(1);}fprintf(stdout, "CLIENT: Connected to server.\n");// Send message to serverconst int buf_len = 256;char buf[buf_len];memset(buf, 0, buf_len);strcpy(buf, "hello from client");rc = send(client_sock, buf, buf_len, 0);if (rc == -1) {fprintf(stderr, "CLIENT: fail to send: %s\n", strerror(errno));exit(1);}fprintf(stdout, "CLIENT: Sent a message to server.\n");fprintf(stdout, "CLIENT: Wait for respond from server...\n");memset(buf, 0, buf_len);rc = recv(client_sock, buf, buf_len, 0);if (rc == -1) {fprintf(stderr, "CLIENT: fail to recv: %s\n", strerror(errno));exit(1);}elsefprintf(stdout, "CLIENT: Message received: %s\n", buf);fprintf(stdout, "CLIENT: Done!\n");close(client_sock);remove(client_sock_path);exit(0);}fprintf(stdout, "====== test finish ======\n");return 0;
}

      编译脚本build.sh如下:

#! /bin/bashif [ -d build ]; thenecho "build directory already exists, it does not need to be created again"
elsemkdir -p build
ficd build
cmake ..
makerc=$?
if [[ ${rc} != 0 ]];thenecho "#### ERROR: please check ####"exit ${rc}
fiecho "==== build finish ===="

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(samples_multi_process)set(CMAKE_BUILD_TYPE Release) # only works under linux
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2 -std=c++17")file(GLOB samples ${PROJECT_SOURCE_DIR}/test_*.cpp)
#message(STATUS "samples: ${samples}")foreach(sample ${samples})string(REGEX MATCH "[^/]+$" name ${sample})string(REPLACE ".cpp" "" exec_name ${name})#message(STATUS "exec name: ${exec_name}")add_executable(${exec_name} ${sample})target_link_libraries(${exec_name} rt)
endforeach()

      执行结果如下所示:

      GitHub:https://github.com/fengbingchun/Linux_Code_Test

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

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

相关文章

jupyter显示内核启动失败或者网络连接失败——解决办法

问题&#xff1a;jupyter显示内核启动失败或者网络连接失败解决: 重新打开cmd&#xff08;anaconda&#xff09;&#xff0c;新建了一个虚拟环境可以啦参考链接&#xff1a;https://blog.csdn.net/cocoink/article/details/129203225

Qt事件处理

1. 事件 众所周知Qt是一个基于C的框架&#xff0c;主要用来开发带窗口的应用程序&#xff08;不带窗口的也行&#xff0c;但不是主流&#xff09;。我们使用的基于窗口的应用程序都是基于事件&#xff0c;其目的主要是用来实现回调&#xff08;因为只有这样程序的效率才是最高…

基于SpringBoot的旅游系统

基于SpringBootVue的旅游系统、前后端分离 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;管理员、用户 用户&#xff1a;浏览旅游…

【论文阅读】内存数据库并发控制算法的实验研究

内存数据库并发控制算法的实验研究 原文链接jos.org.cn/jos/article/pdf/6454 摘要 并发控制算法的基本思想归纳为"先定序后检验”&#xff0c;基于该思想对现有各类并发控制算法进行 了重新描述和分类总结&#xff0c;于在开源内存型分布式事务测试床 3TS 上的实际对比实…

spark中结合源码理解reduceByKey、groupByKey、combineByKey等几个ByKey算子的区别

源码版本&#xff1a;pyspark3.1.2 1.combineByKey2.reduceByKey3.groupByKey4.aggregateByKey5.foldByKey总结 1.combineByKey def combineByKey(self, createCombiner, mergeValue, mergeCombiners,numPartitionsNone, partitionFuncportable_hash):"""Generi…

详解TCP/IP协议第四篇:数据在网络中传输方式的分类概述

文章目录 前言 一&#xff1a;面向有连接型与面向无连接型 1&#xff1a;大致概念 2&#xff1a;面向有连接型 3&#xff1a;面向无连接型 二&#xff1a;电路交换与分组交换 1&#xff1a;分组交换概念 2&#xff1a;分组交交换过程 三&#xff1a;根据接收端数量分…

@SpringBootApplication注解说明(InsCode AI 创作助手)

SpringBootApplication 是 Spring Boot 中的一个关键注解&#xff0c;用于标识一个类是 Spring Boot 应用程序的主应用程序类。在这篇文章中&#xff0c;我们将详细解释 SpringBootApplication 注解以及它在 Spring Boot 应用程序中的作用。 SpringBootApplication 注解的作用…

【操作系统】聊聊CPU上下文切换实操

如何查看系统的上下文切换情况 上一篇文章我们说了过多的上下文切换&#xff0c;会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上&#xff0c;那么当出现系统的上下文切换过多的时候&#xff0c;我们如果通过监控指标查看呢。 vmstat 是一个常用的系统性能…

免费玩云上大数据--海汼部落实验室

玩大数据遇到的问题 大家好&#xff0c;这次分享一个免费的大数据部署工具&#xff0c;并非是给人家打广告&#xff0c;试过了真的爽。 学习大数据的人都知道&#xff0c;如果用VMware模拟Linux搭建大数据集群的话我们需要很高的内存和硬盘内存&#xff0c;随随便便跑一下mapre…

【云原生】Kubernetes学习笔记

部署 在部署前强调几点 不要使用IPv6, 很多组件都不支持IPv6不要使用最新版本, 最新版本非常不稳定, 甚至可能存在无法运行的bug不要版本更新, 安装后就将版本固定下来, 新的版本可能会引入新功能, 或移除旧功能, 导致Kubernetes无法运行 Kubeadm介绍 K8s是由多个模块构成的…

2023华为杯数模C题——大规模创新类竞赛评审方案研究

B题——大规模创新类竞赛评审方案研究 思路&#xff1a;采用数据分析等手段改进评分算法性能 完成情况(1-2问已经完成) 代码下载 问题一 在每个评审阶段&#xff0c;作品通常都是随机分发的&#xff0c;每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比…

解决因为修改SELINUX配置文件出错导致Faild to load SELinux poilcy无法进入CentOS7系统的问题

一、问题 最近学习Kubernetes&#xff0c;需要设置永久关闭SELINUX,结果修改错了一个SELINUX配置参数&#xff0c;关机重新启动后导致无法进入CentOS7系统&#xff0c;卡在启动进度条界面。 二、解决 多次重启后&#xff0c;在启动日志中发现 Faild to load SELinux poilcy…

简单的自托管书签服务NeonLink

什么是 NeonLink &#xff1f; NeonLink 是一个简单且开源的自托管书签服务。它是轻量级的&#xff0c;使用最少的依赖项&#xff0c;并且易于通过 Docker 安装。由于系统要求较低&#xff0c;该应用程序非常适合部署在 RaspberryPI 上。 安装 在群晖上以 Docker 方式安装。 …

【ES6】

ES6 1 ES6简介1.1 什么是ES61.2 为什么使用ES6 2 ES6的新增语法2.1 let2.2 const2.3 let、const、var的区别2.4 解构赋值2.4.1 数组解构2.4.2 对象解构 2.5 箭头函数2.6 剩余参数 3 ES6的内置对象扩展3.1 Array的扩展方法3.1.1 扩展运算符(展开语法)3.1.2 构造函数方法&#xf…

Docker 部署 Bitwarden RS 服务

Bitwarden RS 服务是官方 Bitwarden server API 的 Rust 重构版。因为 Bitwarden RS 必须要通过 https 才能访问, 所以在开始下面的步骤之前, 建议先参考 《Ubuntu Nginx 配置 SSL 证书》 配置好域名和 https 访问。 部署 Bitwarden RS 拉取最新版本的 docker.io/vaultwarden…

vite + vue3 的项目中使用 vitest 做单元测试(仅供参考)

一、配置文件 // vitest.config.tsimport { fileURLToPath } from node:url import { mergeConfig, defineConfig } from vite import { configDefaults } from vitest/config // import viteConfig from ./vite.configimport vue from vitejs/plugin-vue import vueJsx from …

第一百五十二回 自定义组件综合实例:游戏摇杆三

文章目录 内容回顾优化性能示例代码我们在上一章回中介绍了 如何实现游戏摇杆相关的内容,本章回中将继续介绍这方面的知识.闲话休提,让我们一起Talk Flutter吧。 内容回顾 我们在前面章回中介绍了游戏摇杆的概念以及实现方法,并且通过示例代码演示了实现游戏摇杆的整个过程…

Windows安装cuda和cudnn教程最新版(2023年9月)

文章目录 cudacudnn cuda 查看电脑的cuda最高驱动版本&#xff08;适用于N卡电脑-Nvidia&#xff09; winR打开命令行&#xff0c;输入nvidia-smi 右上角cuda -version就是目前支持的最高cuda版本&#xff0c;目前是12.2 nvidia官网下载cuda 下载地址&#xff1a;https://d…

基于eBPF的安卓逆向辅助工具——stackplz

前言 stackplz是一款基于eBPF技术实现的追踪工具&#xff0c;目的是辅助安卓native逆向&#xff0c;仅支持64位进程&#xff0c;主要功能如下&#xff1a; hardware breakpoint 基于pref_event实现的硬件断点功能&#xff0c;在断点处可读取寄存器信息&#xff0c;不会被用户…

C/C++自定义读取ini、cfg配置文件

常见cfg、ini文件如下: [config1] setting192.168.1.1 [config2] setting192.168.1.2 [config3] setting192.168.1.3 示例代码使用 // opt_ini.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> #include "cfg.h"…