当前位置: 首页> 科技> 互联网 > 今天上海新闻_可以接外包的网站_聚名网官网_百度推广代理商查询

今天上海新闻_可以接外包的网站_聚名网官网_百度推广代理商查询

时间:2025/7/15 9:52:59来源:https://blog.csdn.net/JK01WYX/article/details/145848021 浏览次数:0次
今天上海新闻_可以接外包的网站_聚名网官网_百度推广代理商查询

inter process communication

文章目录

  • 管道通信
    • 匿名管道
    • 命名管道
      • 写入端
      • 读取端
  • 消息队列
      • 发送端
      • 接收端:
  • 共享内存
      • 写入端
      • 读取端
  • 信号量
        • PV操作
      • 父子进程
  • 信号
      • 父子进程
  • 套接字
      • 服务器
      • 客户端

管道通信

匿名管道

【单进程内创建父子进程通信】

pipe(int[2])

#include <unistd.h>
#include <iostream>
#include <cstring>int main() {int fd[2];if (pipe(fd) == -1) {perror("pipe创建失败");return 1;}pid_t pid = fork();if (pid < 0) {perror("fork失败");return 1;}if (pid > 0) {  // 父进程(写端)close(fd[0]);  // 关闭读端const char* msg = "来自父进程的消息";write(fd[1], msg, strlen(msg)+1);close(fd[1]);} else {         // 子进程(读端)close(fd[1]);  // 关闭写端char buffer[1024];read(fd[0], buffer, sizeof(buffer));std::cout << "子进程收到: " << buffer << std::endl;close(fd[0]);}return 0;
}

命名管道

写入端

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstring>int main() {const char* fifo_path = "/tmp/my_fifo";// 创建FIFO(如果不存在)if (mkfifo(fifo_path, 0666) == -1) {if(errno != EEXIST) {  // 忽略已存在的错误perror("mkfifo失败");return 1;}}// 打开FIFO进行写入int fd = open(fifo_path, O_WRONLY);if (fd == -1) {perror("打开FIFO失败");return 1;}const char* msg = "通过命名管道发送的消息";write(fd, msg, strlen(msg)+1);close(fd);std::cout << "消息已写入FIFO" << std::endl;return 0;
}

读取端

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>int main() {const char* fifo_path = "/tmp/my_fifo";// 打开FIFO进行读取(会阻塞直到有写入端打开)int fd = open(fifo_path, O_RDONLY);if (fd == -1) {perror("打开FIFO失败");return 1;}char buffer[1024];read(fd, buffer, sizeof(buffer));std::cout << "收到FIFO消息: " << buffer << std::endl;close(fd);return 0;
}

消息队列

接收端会自动清理消息队列

发送端

msgget()
msgsnd()

#include <sys/ipc.h>
#include <sys/msg.h>
#include <iostream>
#include <cstring>struct Message {long type;char text[1024];
};int main() {key_t key = ftok("msgqfile", 65);int msgid = msgget(key, 0666 | IPC_CREAT);Message msg;msg.type = 1;strcpy(msg.text, "通过消息队列发送的消息");if (msgsnd(msgid, &msg, sizeof(msg.text), 0) == -1) {perror("消息发送失败");return 1;}std::cout << "消息已发送: " << msg.text << std::endl;return 0;
}

接收端:

msgget()
msgrcv()
msgctl()

#include <sys/ipc.h>
#include <sys/msg.h>
#include <iostream>struct Message {long type;char text[1024];
};int main() {key_t key = ftok("msgqfile", 65);int msgid = msgget(key, 0666 | IPC_CREAT);Message msg;if (msgrcv(msgid, &msg, sizeof(msg.text), 1, 0) == -1) {perror("消息接收失败");return 1;}std::cout << "收到消息: " << msg.text << std::endl;msgctl(msgid, IPC_RMID, nullptr);  // 清理消息队列return 0;
}

共享内存

对于需要频繁地在多个进程间共享大量数据的场景,共享内存是最佳选择。

通过 key 来标识同一个对象,使得不同进程能够在同一系统中通过这个 key 获取同一对象的文件描述符或者其他标识符。

写入端

shmget()
shmat()
shmdt()

#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
#include <cstring>int main() {key_t key = ftok("shmfile", 65);int shmid = shmget(key, 1024, 0666 | IPC_CREAT);char* str = (char*)shmat(shmid, nullptr, 0);strcpy(str, "共享内存中的消息");std::cout << "写入共享内存: " << str << std::endl;shmdt(str);return 0;
}

读取端

shmget()
shmat()
shmdt()
shmctl()

读取端会主动删除共享内存段
注意实际使用时需要同步机制

#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>int main() {key_t key = ftok("shmfile", 65);int shmid = shmget(key, 1024, 0666 | IPC_CREAT);char* str = (char*)shmat(shmid, nullptr, 0);std::cout << "读取共享内存: " << str << std::endl;shmdt(str);shmctl(shmid, IPC_RMID, nullptr);  // 删除共享内存return 0;
}

信号量

当需要控制多个进程对共享资源的访问顺序,或者实现进程之间的同步时,信号量是必不可少的工具。

PV操作

P操作(荷兰语单词 “proberen”(尝试)的首字母):通常称为 “wait” 或 “down” 操作。
wait:等待信号量的值变为大于零,然后将其减一。
down:将信号量的值减一,若信号量值为零,则进入等待队列。

V 操作(V 是荷兰语单词 “verhogen”(增加)的首字母):通常称为 “signal” 或 “up” 操作,表示将信号量的值加一。
signal*:表示释放资源,信号量的值加一,并唤醒因 P 操作而被阻塞的进程。
up:将信号量值加一,表示资源的释放。

struct sembuf
semget()
semctl()
semop()

父子进程

(即便不是父子进程,多个进程也可以通过相同的 SEM_KEY 来访问同一个信号量集)

// semaphore_example.cpp
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>#define SEM_KEY 1234  // 信号量的键值// 定义信号量操作结构体
struct sembuf sem_op;int main() {// 获取信号量的标识符int sem_id = semget(SEM_KEY, 1, IPC_CREAT | 0666);if (sem_id == -1) {perror("semget failed");return 1;}// 初始化信号量semctl(sem_id, 0, SETVAL, 1);  // 初始化信号量的值为1pid_t pid = fork();if (pid == 0) {// 子进程:等待信号量(P操作)sem_op.sem_num = 0;sem_op.sem_op = -1;  // P操作,减少信号量sem_op.sem_flg = 0;semop(sem_id, &sem_op, 1);std::cout << "Child process: Critical section accessed\n";// 临界区访问完毕,释放信号量(V操作)sem_op.sem_op = 1;  // V操作,增加信号量semop(sem_id, &sem_op, 1);} else {// 父进程:等待信号量(P操作)sem_op.sem_num = 0;sem_op.sem_op = -1;  // P操作sem_op.sem_flg = 0;semop(sem_id, &sem_op, 1);std::cout << "Parent process: Critical section accessed\n";// 临界区访问完毕,释放信号量(V操作)sem_op.sem_op = 1;  // V操作semop(sem_id, &sem_op, 1);}// 删除信号量semctl(sem_id, 0, IPC_RMID);return 0;
}

信号

signal()
kill()

父子进程

// signal_example.cpp
#include <iostream>
#include <csignal>
#include <unistd.h>void signal_handler(int sig) {if (sig == SIGUSR1) {std::cout << "Received SIGUSR1 signal in process: " << getpid() << std::endl;}
}int main() {signal(SIGUSR1, signal_handler);  // 注册信号处理函数pid_t pid = fork();if (pid == 0) {// 子进程:发送信号sleep(2);std::cout << "Child process: Sending SIGUSR1 to parent process\n";kill(getppid(), SIGUSR1);  // 向父进程发送信号} else {// 父进程:等待信号std::cout << "Parent process: Waiting for signal\n";pause();  // 等待信号}return 0;
}

套接字

不同主机之间进程只能通过套接字通信

struct sockaddr_un 【sun_family】【sun_path】
socket(AF_UNIX, SOCK_STREAM, 0)

(SOCK_STREAM:面向连接的套接字类型,表示 TCP 协议。)
这里是:
Unix 域套接字是专门设计用来在同一台机器上运行的进程之间进行通信的。
不需要通过网络栈来进行数据传输,所有的数据传输都发生在内核空间内。这样可以避免网络协议栈的开销,减少了数据传输的延迟。使用TCP套接字:
struct sockaddr_in(IPv4) 或 struct sockaddr_in6(IPv6)
AF_INET:IPv4 网络协议(如果你要使用 TCP 连接并且是 IPv4 地址)。
AF_INET6:IPv6 网络协议(如果你要使用 TCP 连接并且是 IPv6 地址)。

unlink()
bind()
listen()
accept()
send()


connect()
send()
recv()

服务器

// server.cpp
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>#define SOCKET_PATH "/tmp/unix_socket"int main() {int server_fd, client_fd;struct sockaddr_un addr, client_addr;socklen_t client_len = sizeof(client_addr);// 创建 Unix 域套接字server_fd = socket(AF_UNIX, SOCK_STREAM, 0);if (server_fd == -1) {perror("socket");return 1;}addr.sun_family = AF_UNIX;strcpy(addr.sun_path, SOCKET_PATH);unlink(SOCKET_PATH);  // 删除已有的 socket 文件// 绑定套接字if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {perror("bind");return 1;}// 监听连接if (listen(server_fd, 1) == -1) {perror("listen");return 1;}std::cout << "Server waiting for connection...\n";// 接受客户端连接client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);if (client_fd == -1) {perror("accept");return 1;}std::cout << "Client connected. Waiting for message...\n";char buffer[256];ssize_t len = read(client_fd, buffer, sizeof(buffer) - 1);if (len > 0) {buffer[len] = '\0';std::cout << "Server received: " << buffer << std::endl;// 服务器向客户端发送回应消息const char* response = "Message received by server!";send(client_fd, response, strlen(response), 0);}close(client_fd);close(server_fd);return 0;
}

客户端

// client.cpp
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>#define SOCKET_PATH "/tmp/unix_socket"int main() {int sock;struct sockaddr_un addr;// 创建 Unix 域套接字sock = socket(AF_UNIX, SOCK_STREAM, 0);if (sock == -1) {perror("socket");return 1;}addr.sun_family = AF_UNIX;strcpy(addr.sun_path, SOCKET_PATH);// 连接到服务器if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {perror("connect");return 1;}const char* message = "Hello from client!";if (send(sock, message, strlen(message), 0) == -1) {perror("send");return 1;}std::cout << "Client sent message: " << message << std::endl;close(sock);return 0;
}
关键字:今天上海新闻_可以接外包的网站_聚名网官网_百度推广代理商查询

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: