当前位置: 首页 > news >正文

做内衣批发的网站好seo收录查询工具

做内衣批发的网站好,seo收录查询工具,做网站的主流软件,深圳做app网站的公司我们的目的是,实现进程间传递文件描述符,是指 A进程打开文件fileA,获得文件描述符为fdA,现在 A进程要通过某种方法,传递fdA,使得另一个进程B,获得一个新的文件描述符fdB,这个fdB在进程B中的作用…

        我们的目的是,实现进程间传递文件描述符,是指 A进程打开文件fileA,获得文件描述符为fdA,现在 A进程要通过某种方法,传递fdA,使得另一个进程B,获得一个新的文件描述符fdB,这个fdB在进程B中的作用,跟fdA在进程A中的作用一样。即在 fdB上的操作,即是对fileA的操作。

        可能很多人想到的是用管道pipe来实现,但是却没想象的那么容易。

1.了解fork函数

首先需要知道,在调用 fork() 函数之前打开的文件,其文件描述符会被复制到子进程中。这是因为在 fork() 函数执行时,操作系统会创建子进程,而子进程将复制父进程的地址空间,包括文件描述符表。因此,父进程打开的文件描述符会被子进程继承并复制到子进程的文件描述符表中。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main() {int file_fd;pid_t pid;char buf[1024];// 打开文件file_fd = open("file.txt", O_RDONLY);if (file_fd == -1) {perror("open");exit(EXIT_FAILURE);}// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {// 子进程ssize_t num_read;// 使用父进程打开的文件描述符操作文件while ((num_read = read(file_fd, buf, sizeof(buf))) > 0) {write(STDOUT_FILENO, buf, num_read);}if (num_read == -1) {perror("read");exit(EXIT_FAILURE);}close(file_fd);  // 关闭文件描述符_exit(EXIT_SUCCESS);  // 退出子进程} else {// 父进程int status;// 等待子进程结束wait(&status);// 关闭文件描述符close(file_fd);if (WIFEXITED(status)) {printf("子进程正常退出,退出状态码:%d\n", WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {printf("子进程异常终止,信号编号:%d\n", WTERMSIG(status));}}return 0;
}

其次,在父进程调用 fork() 函数之后打开的文件,子进程不会自动继承这些新打开的文件描述符。也就是说,父进程在 fork() 之后打开的文件描述符,只在父进程的文件描述符表中有效,子进程不会获得这些文件描述符。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>int main() {int file_fd;pid_t pid;char buf[1024];// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {// 子进程printf("子进程开始...\n");// 尝试读取父进程在fork之后打开的文件描述符(这里没有实际的文件描述符,所以操作会失败)ssize_t num_read = read(3, buf, sizeof(buf)); // 假设文件描述符3是父进程在fork之后打开的if (num_read == -1) {perror("子进程无法读取文件(因为没有继承父进程在fork之后打开的文件描述符)");} else {write(STDOUT_FILENO, buf, num_read);}_exit(EXIT_SUCCESS);  // 退出子进程} else {// 父进程int status;// 在fork之后打开文件file_fd = open("file.txt", O_RDONLY);if (file_fd == -1) {perror("open");exit(EXIT_FAILURE);}printf("父进程打开的文件描述符: %d\n", file_fd);// 等待子进程结束wait(&status);// 关闭文件描述符close(file_fd);if (WIFEXITED(status)) {printf("子进程正常退出,退出状态码:%d\n", WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {printf("子进程异常终止,信号编号:%d\n", WTERMSIG(status));}}return 0;
}

结论:

  • fork() 之前打开的文件描述符,子进程会继承并可以使用。
  • fork() 之后打开的文件描述符,子进程不会继承,无法直接使用这些文件描述符。

2.使用管道pipe传递文件描述符的问题

下面是使用管道pipe传递文件描述符的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>#define BUF_SIZE 1024int main() {int pipe_fd[2]; // 管道的文件描述符数组int file_fd;    // 文件的文件描述符pid_t pid;char buf[BUF_SIZE];// 创建管道if (pipe(pipe_fd) == -1) {perror("pipe");exit(EXIT_FAILURE);}// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {// 子进程close(pipe_fd[1]); // 关闭子进程不需要的写入端// 从管道中读取父进程传递的文件描述符int received_fd;read(pipe_fd[0], &received_fd, sizeof(int));printf("received_fd:%d\n", received_fd);// 使用接收到的文件描述符操作文件Assize_t num_read;while ((num_read = read(received_fd, buf, BUF_SIZE)) > 0) {write(STDOUT_FILENO, buf, num_read); // 在子进程中输出文件内容}if (num_read == -1) {perror("read");exit(EXIT_FAILURE);}close(received_fd); // 关闭文件描述符close(pipe_fd[0]);  // 关闭管道读取端_exit(EXIT_SUCCESS); // 退出子进程} else {// 父进程close(pipe_fd[0]); // 关闭父进程不需要的读取端// 打开文件A并获取文件描述符file_fd = open("fileA.txt", O_RDONLY);if (file_fd == -1) {perror("open");exit(EXIT_FAILURE);}printf("file_fd:%d\n", file_fd);// 将文件描述符写入管道,传递给子进程if (write(pipe_fd[1], &file_fd, sizeof(int)) != sizeof(int)) {perror("write");exit(EXIT_FAILURE);}close(file_fd);    // 关闭父进程中的文件描述符close(pipe_fd[1]); // 关闭管道写入端wait(NULL);        // 等待子进程结束exit(EXIT_SUCCESS); // 退出父进程}
}

失败的原因:在代码中,父进程使用 write(pipe_fd[1], &file_fd, sizeof(int))file_fd 写入管道的写入端。这一步骤本质上是将一个整数(文件描述符)写入到管道中。在Unix-like系统中,文件描述符是进程特定的,它们不能简单地通过整数值在不同的进程之间传递。直接通过管道传递文件描述符的整数值是无效的,因为文件描述符是相对于进程的。

要正确地传递文件描述符,必须使用sendmsgrecvmsg系统调用,以及SCM_RIGHTS控制消息。这些系统调用允许在进程间传递文件描述符,而不仅仅是它们的整数值。

3.相关操作函数

3.1socketpair 函数

socketpair 函数用于在本地创建一对连接的套接字,通常用于同一主机上的进程间通信。它创建了一个双向通道,使得两个相关联的套接字可以在两个进程之间传递数据,实现全双工通信。socketpair 通常用于需要在同一台主机上的不同进程之间进行高效通信的场景。例如,父子进程间或者同一程序的不同线程之间。

#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sv[2]);
参数详解
domain:指定套接字的协议族,通常为 AF_UNIX(Unix 域套接字),用于本地进程间通信。
type:指定套接字的类型,常见的有:SOCK_STREAM:提供面向连接的、可靠的数据传输服务(如 TCP)。SOCK_DGRAM:提供无连接、不可靠的数据传输服务(如 UDP)。
protocol:指定套接字使用的协议,一般为 0,表示使用默认协议。
sv[2]:一个整型数组,用于存放创建的套接字对的文件描述符。在调用 socketpair 函数后,sv[0] 和 sv[1] 分别包含这两个相关联的套接字的文件描述符。
返回值:
成功时返回 0。
失败时返回 -1,并设置 errno 指示错误的类型。

3.2 sendmsg函数

sendmsg 函数用于向指定套接字发送消息,支持发送多块数据和控制消息(例如文件描述符)。

#include <sys/socket.h>
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
参数详解
sockfd:指定发送消息的套接字描述符。
msg:
指向 struct msghdr 结构体的指针,描述了要发送的消息的详细信息,包括数据块 (iovec 结构体数组) 和控制消息 (cmsghdr 结构体)。
flags:通常为 0,用于控制消息发送的附加选项。
返回值:
成功时返回发送的字节数。
失败时返回 -1,并设置 errno 指示错误的类型。

3.3 recvmsg函数

recvmsg 函数用于从指定套接字接收消息,支持接收多块数据和控制消息(例如文件描述符)。

#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
参数详解
sockfd:指定接收消息的套接字描述符。
msg:
指向 struct msghdr 结构体的指针,用于存放接收到的消息的详细信息,包括数据块 (iovec 结构体数组) 和控制消息 (cmsghdr 结构体)。
flags:通常为 0,用于控制消息接收的附加选项。
返回值:
成功时返回发送的字节数。
失败时返回 -1,并设置 errno 指示错误的类型。

3.4 struct msghdr 结构体详解

struct msghdr {void         *msg_name;       // 指向目标地址的指针socklen_t    msg_namelen;     // 目标地址的长度struct iovec *msg_iov;        // 数据块的数组size_t       msg_iovlen;      // 数据块数组的长度void         *msg_control;    // 控制消息的指针size_t       msg_controllen;  // 控制消息的长度int          msg_flags;       // 消息的标志
};
结构体成员:msg_name 和 msg_namelen:用于指定目标地址的信息,通常用于 UDP 套接字。msg_iov 和 msg_iovlen:用于指定数据块的数组和数组长度,支持数据的分散/聚集操作。msg_control 和 msg_controllen:用于处理控制消息(如文件描述符)的指针和长度。msg_flags:用于指定消息的标志,例如 MSG_DONTWAIT 等。struct iovec {void  *iov_base; // 指向数据缓冲区的指针size_t iov_len;  // 数据缓冲区的长度
};
成员解释:iov_base:指向数据缓冲区的指针,即存放数据的内存地址。iov_len:数据缓冲区的长度,即缓冲区中可以传输的数据的字节数。
  • 工作原理

    • sendmsg 函数通过 msg 结构体描述要发送的数据块和控制消息。
    • recvmsg 函数从套接字接收数据,并将接收到的数据填充到 msg 结构体中指定的缓冲区中。
  • 控制消息传递

    • sendmsgrecvmsg 支持通过 msg_controlmsg_controllen 参数传递控制消息(cmsghdr 结构体),特别是用于传递文件描述符等特殊信息。
  • 应用场景

    • 进程间通信(IPC):sendmsgrecvmsg 可以在进程间传递复杂的数据结构和文件描述符,适用于需要高效数据传输和资源共享的场景。
    • 网络编程:在网络编程中,这两个函数用于向套接字发送数据和从套接字接收数据,支持分散/聚集操作和控制消息传递。

作用

  • struct iovec 结构体主要用于描述 msg_iov 参数,即 struct msghdr 结构体中的数据块数组。它允许用户指定多个数据块的位置和长度,从而实现数据的分散(scatter)和聚集(gather)操作。

3.5 writev 和 readv 函数

操作 struct iovec 结构体的系统调用主要用于实现数据的分散读(scatter)和聚集写(gather)操作,这些操作通常用于高效地传输多个数据块。

功能

  • writev 函数将多个数据块从 iov 指定的缓冲区中写入到文件描述符 fd 所指定的文件中。
  • readv 函数从文件描述符 fd 所指定的文件中读取数据,并存储到 iov 指定的多个缓冲区中。
#include <sys/uio.h>
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
参数:fd:文件描述符,表示要读写的文件。iov:指向 struct iovec 结构体数组的指针,描述要读写的数据块及其位置。iovcnt:iov 数组中元素的个数,即要读写的数据块的数量。
返回值:
成功时返回读写的字节数。
失败时返回 -1,并设置 errno 指示错误的类型。
  • 工作原理

    • writev 函数将 iov 数组中描述的多个数据块依次写入到文件描述符 fd 指定的文件中。
    • readv 函数从文件描述符 fd 指定的文件中读取数据,并将数据依次存储到 iov 数组中指定的多个缓冲区中。
  • 数据传输

    • writevreadv 函数支持数据的分散(scatter)和聚集(gather)操作,可以高效地处理多个非连续数据块的读写。
  • 应用场景

    • 在网络编程中,writevreadv 可以用于同时发送或接收多个数据块,提高数据传输的效率。
    • 在文件操作中,对于需要同时读写多个缓冲区数据的场景,如日志文件写入等,也可以使用这两个函数。

4.示例代码

将父进程中得到文件描述符传递给子进程,子进程得到该文件描述符同样可以操作该文件,实现文件描述符在进程间真正的传递。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>void send_fd(int socket, int fd_to_send) {struct msghdr msg = {0};          // 定义消息头结构体并初始化struct iovec iov[1];              // 定义数据块结构体数组struct cmsghdr *cmsg;             // 定义控制消息头指针char control[CMSG_SPACE(sizeof(int))]; // 控制信息缓冲区char dummy = '*';                 // 用于填充数据块的虚拟字符iov[0].iov_base = &dummy;         // 设置数据块的基址为虚拟字符的地址iov[0].iov_len = 1;               // 设置数据块的长度为1字节msg.msg_iov = iov;                // 设置消息头的数据块数组msg.msg_iovlen = 1;               // 设置数据块数组的长度msg.msg_control = control;        // 设置消息头的控制信息msg.msg_controllen = sizeof(control); // 设置控制信息的长度cmsg = CMSG_FIRSTHDR(&msg);       // 获取第一个控制消息头cmsg->cmsg_level = SOL_SOCKET;    // 设置控制消息级别为套接字级别cmsg->cmsg_type = SCM_RIGHTS;     // 设置控制消息类型为传递文件描述符cmsg->cmsg_len = CMSG_LEN(sizeof(int)); // 设置控制消息长度*((int *) CMSG_DATA(cmsg)) = fd_to_send; // 将待发送的文件描述符复制到控制消息的数据部分if (sendmsg(socket, &msg, 0) == -1) { // 发送消息perror("sendmsg");}
}int recv_fd(int socket) {struct msghdr msg = {0};          // 定义消息头结构体并初始化struct iovec iov[1];              // 定义数据块结构体数组struct cmsghdr *cmsg;             // 定义控制消息头指针char control[CMSG_SPACE(sizeof(int))]; // 控制信息缓冲区char dummy;                       // 用于填充数据块的虚拟字符iov[0].iov_base = &dummy;         // 设置数据块的基址为虚拟字符的地址iov[0].iov_len = 1;               // 设置数据块的长度为1字节msg.msg_iov = iov;                // 设置消息头的数据块数组msg.msg_iovlen = 1;               // 设置数据块数组的长度msg.msg_control = control;        // 设置消息头的控制信息msg.msg_controllen = sizeof(control); // 设置控制信息的长度if (recvmsg(socket, &msg, 0) == -1) { // 接收消息perror("recvmsg");return -1;}cmsg = CMSG_FIRSTHDR(&msg);       // 获取第一个控制消息头unsigned char *data = CMSG_DATA(cmsg); // 获取控制消息的数据部分int fd = *((int *) data);         // 提取文件描述符return fd;                        // 返回接收到的文件描述符
}int main() {int socket_pair[2]; // 套接字对int file_fd;        // 文件的文件描述符pid_t pid;char buf[1024];// 创建套接字对if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1) {perror("socketpair");exit(EXIT_FAILURE);}// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {// 子进程close(socket_pair[1]); // 关闭子进程不需要的写入端// 从套接字中读取父进程传递的文件描述符int received_fd = recv_fd(socket_pair[0]);// 使用接收到的文件描述符操作文件Assize_t num_read;while ((num_read = read(received_fd, buf, sizeof(buf))) > 0) {write(STDOUT_FILENO, buf, num_read); // 在子进程中输出文件内容}if (num_read == -1) {perror("read");exit(EXIT_FAILURE);}close(received_fd); // 关闭文件描述符close(socket_pair[0]);  // 关闭套接字读取端_exit(EXIT_SUCCESS); // 退出子进程} else {// 父进程close(socket_pair[0]); // 关闭父进程不需要的读取端// 在fork后打开文件并获取文件描述符file_fd = open("fileA.txt", O_RDONLY);if (file_fd == -1) {perror("open");exit(EXIT_FAILURE);}// 将文件描述符通过套接字传递给子进程send_fd(socket_pair[1], file_fd);close(file_fd);    // 关闭父进程中的文件描述符close(socket_pair[1]); // 关闭套接字写入端wait(NULL);        // 等待子进程结束exit(EXIT_SUCCESS); // 退出父进程}return 0;
}


文章转载自:
http://highflyer.ptzf.cn
http://chemmy.ptzf.cn
http://lardoon.ptzf.cn
http://karpinskyite.ptzf.cn
http://deraignment.ptzf.cn
http://evaluating.ptzf.cn
http://endospore.ptzf.cn
http://pamper.ptzf.cn
http://fencing.ptzf.cn
http://thioarsenite.ptzf.cn
http://ischial.ptzf.cn
http://mushroomy.ptzf.cn
http://restrictively.ptzf.cn
http://clapnet.ptzf.cn
http://intramuscular.ptzf.cn
http://redaction.ptzf.cn
http://calligraphist.ptzf.cn
http://speleology.ptzf.cn
http://hydrocyanic.ptzf.cn
http://heintzite.ptzf.cn
http://trichogen.ptzf.cn
http://corolla.ptzf.cn
http://casey.ptzf.cn
http://dewclaw.ptzf.cn
http://ridgepole.ptzf.cn
http://archiphoneme.ptzf.cn
http://antichlor.ptzf.cn
http://architectonic.ptzf.cn
http://diagonalize.ptzf.cn
http://mustang.ptzf.cn
http://preludious.ptzf.cn
http://pituitrin.ptzf.cn
http://said.ptzf.cn
http://scunner.ptzf.cn
http://rot.ptzf.cn
http://royston.ptzf.cn
http://caproate.ptzf.cn
http://surveyal.ptzf.cn
http://peignoir.ptzf.cn
http://oddfellow.ptzf.cn
http://plim.ptzf.cn
http://vera.ptzf.cn
http://fio.ptzf.cn
http://polygenism.ptzf.cn
http://snelskrif.ptzf.cn
http://preestablish.ptzf.cn
http://unstop.ptzf.cn
http://disciform.ptzf.cn
http://footbridge.ptzf.cn
http://evangelist.ptzf.cn
http://ropeway.ptzf.cn
http://cyclone.ptzf.cn
http://haliver.ptzf.cn
http://chevroler.ptzf.cn
http://batteries.ptzf.cn
http://tripod.ptzf.cn
http://seclusively.ptzf.cn
http://trayful.ptzf.cn
http://simba.ptzf.cn
http://lucarne.ptzf.cn
http://titrimetry.ptzf.cn
http://newspaperman.ptzf.cn
http://adsorbability.ptzf.cn
http://styrolene.ptzf.cn
http://prolongation.ptzf.cn
http://bubu.ptzf.cn
http://credal.ptzf.cn
http://inaptitude.ptzf.cn
http://way.ptzf.cn
http://turbinoid.ptzf.cn
http://erythromelalgia.ptzf.cn
http://bitcasting.ptzf.cn
http://galluses.ptzf.cn
http://derious.ptzf.cn
http://transconductance.ptzf.cn
http://flibbertigibbet.ptzf.cn
http://smacker.ptzf.cn
http://phenetic.ptzf.cn
http://demargarinated.ptzf.cn
http://andvar.ptzf.cn
http://hickey.ptzf.cn
http://hardmouthed.ptzf.cn
http://kastelorrizon.ptzf.cn
http://maglev.ptzf.cn
http://unnamable.ptzf.cn
http://maharashtrian.ptzf.cn
http://indiscoverable.ptzf.cn
http://alacritous.ptzf.cn
http://leprosarium.ptzf.cn
http://cate.ptzf.cn
http://leukemia.ptzf.cn
http://hommock.ptzf.cn
http://haemochrome.ptzf.cn
http://krebs.ptzf.cn
http://headteacher.ptzf.cn
http://orzo.ptzf.cn
http://takeup.ptzf.cn
http://physicky.ptzf.cn
http://costing.ptzf.cn
http://rend.ptzf.cn
http://www.15wanjia.com/news/92108.html

相关文章:

  • 成都网站优化排名创建网站需要什么条件
  • 网站图标怎么做江小白网络营销案例
  • 加建网网站谷歌seo排名优化服务
  • 郑州模板网站制作软文推广多少钱
  • 企业网站网站建设电话百度贴吧的互动社区
  • 什么软件网站好新塘网站seo优化
  • 宁夏建设工程招标投标管理中心网站品牌推广公司
  • 网站制作软件安卓版牡丹江网站seo
  • 晋江哪里可以学建设网站seo下载站
  • 青海建设兵团青岛战友网站磁力棒
  • 响应式网站源码下载政府免费培训面点班
  • 怎么建立一个独立的网站百度 搜索热度
  • 移动网络营销是什么网站seo设计
  • 做网站用别人图片文章会侵权吗优化关键词的公司
  • 网上墓地 wordpressseo关键词优化推广
  • 廊坊做网站价格拓客最有效方案
  • 做2手车网站需要多少钱设计培训班学费一般多少
  • 重庆做网站建设公司域名解析查询工具
  • 什么程序做教育网站好黑马it培训班出来现状
  • 网站开发竞争对手分析国际时事新闻
  • apache创建WordPress谷歌优化seo
  • 做全网影视网站的风险百度引擎搜索网址
  • 各大网站的404网站建设需求模板
  • 给别人做的网站涉及到诈骗抖音seo软件工具
  • 做电影网站被告版权免费手机网站建站平台
  • 对电子商务网站建设与管理的理解外链工具软件
  • 注册网站主体想找回备案如何做国外seo网站
  • 建个人网站做导购网站监测
  • 网站建设人才有哪些全自动在线网页制作
  • 电子商务网站计划书bt种子搜索