用libuv库实现管道进程间通信

本文通过实例展示了如何使用libuv库中的pipe功能进行进程间通信,客户端借助readline库接收控制台输入,并将命令传递给服务端,服务端与客户端之间实现数据交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:本实例利用了libuv库中的pipe管道实现进程通信,类似与本地套接字。客户端连接服务器端建立连接后相互发送数据

客户端使用了readline库实现控制台输入命令,客户端将命令字符串传给服务端。


服务端:

文件LocalServer.h

#pragma once
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

using namespace std;
#define PIPENAME "pipe.sock"
extern "C"
{
    #include "uv.h"
    #include "uv-errno.h"
}

class LocalServer;

typedef struct{
    uv_pipe_t server_client;
    LocalServer *ts;
}UvPipe;

class LocalServer
{
public:
    LocalServer();
    ~LocalServer();

    int initLocalServer(uv_loop_t* loop);
    static void remove_sock(int sig);
    static void onPipeConnectionCb(uv_stream_t* server,int status);
    void onPipeConnection(uv_stream_t* server,int status);
    static void onPipeReadCb(uv_stream_t* client,ssize_t nread,const uv_buf_t* buf);
    void onPipeRead(uv_stream_t* client,ssize_t nread,const uv_buf_t* buf);
    static void allocPipeBufferCb(uv_handle_t* handle,size_t suggested_size,uv_buf_t* buf);
    void allocPipeBuffer(uv_handle_t* handle,size_t suggested_size,uv_buf_t* buf);

private:
    uv_loop_t* mLoop;
    UvPipe pipeServer;
};

文件:LocalServer.cpp

#include "LocalServer.h"

LocalServer::LocalServer()
{
}

LocalServer::~LocalServer()
{
}


int LocalServer::initLocalServer(uv_loop_t* loop)
{
    if(loop==NULL)
    {
        cout<<"mllop is null   "<<endl;
    }
    mLoop=loop;

    //若sock文件PIPENAME存在则删除
    uv_fs_t req;
    uv_fs_unlink(mLoop,&req,PIPENAME,NULL);
    uv_pipe_init(mLoop,(uv_pipe_t*)&pipeServer,0);
    //程序终止时删除sock文件PIPENAME
    signal(SIGINT,remove_soc
<think>我们正在寻找用于本地进程间通信(LPC)的C语言。根据之前的回答和引用,我们可以总结出几种常见的实现方式:1.**套接字(Socket)**:特别是UNIX域套接字(本地套接字),它不需要网络协议栈,效率较高[^1][^3]。2.**管道(Pipe)**:包括匿名管道和命名管道(FIFO),是Unix-like系统中传统的IPC方式[^2][^4]。3.**共享内存**:通过映射一段能被其他进程访问的内存来实现高速通信[^4]。4.**消息队列**:在内核中维护的消息链表,允许进程以消息形式交换数据[^4]。5.**信号(Signal)**:用于异步通知,但传递的信息有限[^5]。但是,用户要求的是“”,即封装好的C,而不是直接使用系统调用。因此,我们可以推荐以下:###推荐####1.**libuv**-跨平台异步I/O-**特点**:-支持UNIX域套接字(本地套接字)和命名管道-事件驱动,高性能-被Node.js使用,稳定可靠-**示例(UNIX域套接字)**:```c#include<uv.h>uv_loop_t*loop=uv_default_loop();uv_pipe_tserver;uv_pipe_init(loop,&server,0);//0表示非跨进程,1表示跨进程(使用命名管道)uv_pipe_bind(&server,"/tmp/mypipe.sock");```####2.**ZeroMQ**-高性能消息-**特点**:-支持多种传输方式,包括`ipc://`(进程间通信)和`inproc://`(线程间通信)-提供多种通信模式(请求-响应、发布-订阅等)-跨平台-**示例(使用IPC)**:```c#include<zmq.h>void*ctx=zmq_ctx_new();void*responder=zmq_socket(ctx,ZMQ_REP);zmq_bind(responder,"ipc:///tmp/lpc.ipc");```####3.**nanomsg/nng**-ZeroMQ的轻量级替代-**特点**:-更现代的API,更轻量-支持类似的IPC机制-**示例**:```c#include<nng/nng.h>#include<nng/protocol/reqrep0/rep.h>nng_socketsock;nng_rep0_open(&sock);nng_listen(sock,"ipc:///tmp/lpc.ipc",NULL,0);```####4.**glib**-GNOME基础,提供IPC抽象-**特点**:-提供GIOChannel,支持管道、套接字等-事件循环集成-适合GNOME或GTK应用-**示例(命名管道)**:```c#include<glib.h>GIOChannel*channel=g_io_channel_new_file("/tmp/mypipe","r",NULL);```####5.**ApacheAPR**-Apache可移植运行-**特点**:-跨平台,抽象了操作系统差异-提供共享内存、管道、套接字等IPC机制-**示例(共享内存)**:```c#include<apr_shm.h>apr_shm_t*shm;apr_shm_create(&shm,size,NULL,pool);void*base=apr_shm_baseaddr_get(shm);```###选择建议-**需要事件驱动和高性能**:选择**libuv**或**ZeroMQ**。-**轻量级和简单性**:选择**nng**。-**集成到GNOME/GTK应用**:选择**glib**。-**跨平台兼容性**:**ApacheAPR**或**libuv**。###相关问题1.如何比较libuv和ZeroMQ在本地进程间通信的性能?2.在嵌入式系统中使用哪种IPC最合适?3.使用UNIX域套接字和命名管道有何区别?4.如何保证IPC通信的安全性(例如,防止未授权访问)?[^1]:Socket编程:C语言使用socket进行本地进程间通信、网络通信。[^2]:第十章本地进程间通信管道)。[^3]:进程与线程(四)——进程间通信。[^4]:LinuxC进程间通信。[^5]:C语言实现进程间通信。</think>### 适合本地进程间通信的C语言推荐 根据您的需求和相关引用资料,以下是专为**本地进程间通信(LPC)**设计的C语言推荐,重点关注高性能、低延迟和易用性: --- #### 1. **UNIX域套接字 (Sockets for IPC)** [^1][^3] - **特点**: - 原生支持Linux/Unix系统,无需额外依赖 - 使用文件系统路径作为通信端点(如`/tmp/mypipe.sock`) - 支持流式(`SOCK_STREAM`)和数据报(`SOCK_DGRAM`)模式 - 性能接近网络套接字但无网络开销 - **示例代码**: ```c // 服务端 int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un addr = {.sun_family = AF_UNIX}; strcpy(addr.sun_path, "/tmp/mypipe.sock"); bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); listen(sockfd, 5); // 客户端 int fd = socket(AF_UNIX, SOCK_STREAM, 0); connect(fd, (struct sockaddr*)&addr, sizeof(addr)); ``` #### 2. **命名管道 (Named Pipes/FIFO)** [^2][^4] - **特点**: - 通过文件系统节点通信(`mkfifo()`创建) - 单向通信,适合生产者-消费者模型 - 内核级缓冲区管理 - 超时控制机制(引用[2]中的`closetimeout`) - **示例代码**: ```c // 创建FIFO mkfifo("/tmp/myfifo", 0666); // 进程A写入 int fd = open("/tmp/myfifo", O_WRONLY); write(fd, "Hello", 6); // 进程B读取 int fd = open("/tmp/myfifo", O_RDONLY); char buf[32]; read(fd, buf, sizeof(buf)); ``` #### 3. **共享内存 (Shared Memory)** [^4] - **特点**: - 最快IPC方式,通过映射相同物理内存 - 需配合信号量/互斥锁同步 - 适用大数据量传输(如图像处理) - **关键函数**: ```c shmget() // 创建共享内存段 shmat() // 附加到进程地址空间 shmdt() // 分离内存段 ``` #### 4. **D-Bus (针对桌面环境)** - **特点**: - 支持方法调用、信号发布、对象管理 - 自动序列化/反序列化 - 会话总线(同一用户)和系统总线(全局) - **安装**: ```bash sudo apt-get install libdbus-1-dev # Debian/Ubuntu ``` #### 5. **ZeroMQ + IPC传输** - **特点**: - 使用`ipc://`协议代替`tcp://` - 内置消息队列和重试机制 - 支持多对多通信模式 - **示例**: ```c // 绑定端 void *responder = zmq_socket(ctx, ZMQ_REP); zmq_bind(responder, "ipc:///tmp/lpc.ipc"); // 连接端 void *requester = zmq_socket(ctx, ZMQ_REQ); zmq_connect(requester, "ipc:///tmp/lpc.ipc"); ``` --- ### 选择建议表 | 场景 | 推荐方案 | 性能 | 复杂度 | |-----------------------|-----------------------|------|--------| | 简单命令/控制 | 命名管道(FIFO) | ★★☆ | ★☆☆ | | 结构化数据交换 | UNIX域套接字 | ★★★ | ★★☆ | | 高速大数据传输 | 共享内存 + 信号量 | ★★★ | ★★★ | | 桌面应用服务调用 | D-Bus | ★★☆ | ★★☆ | | 分布式进程协作 | ZeroMQ IPC | ★★★ | ★★☆ | > 本地IPC的核心是**内核缓冲区机制**:进程1将数据从用户空间复制到内核缓冲区,进程2再从内核缓冲区读取数据[^4]。这种设计避免了进程间的直接内存访问,保证了安全性。 --- ### 相关问题 1. UNIX域套接字和TCP套接字在性能上有何差异? 2. 如何确保共享内存通信的线程安全性? 3. D-Bus在非桌面环境中是否适用? 4. ZeroMQ的IPC传输协议如何避免消息丢失? 5. 命名管道(FIFO)的阻塞和非阻塞模式有何区别? [^1]: Socket编程:C语言使用socket进行本地进程间通信、网络通信。 [^2]: 第十章 本地进程间通信管道)。 [^3]: 进程与线程(四)——进程间通信。 [^4]: Linux C 进程间通信。 [^5]: C语言实现进程间通信
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值