Linux 管道、mmap文件映射

本文深入探讨了Linux系统中的管道在I/O多路复用模型中的应用,详细解释了select函数如何从文件描述符中选择可用的进行读写。同时,文章介绍了mmap技术如何实现大文件的高效复制,指出其利用磁盘驱动器硬件直接将文件映射到内存,避免了内核与用户空间的数据交换,速度优于传统的cp命令。最后,提到了大文件生成的两种方式。

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

1.管道实现I/O多路转接模型
仔细理解select函数 从文件描述符集合选择可用的
例如: stdio 0 以及read 管道fifo中的数据这两个文件描述符中选取可以使用的,并加以判断FD_ISSET哪个fd描述符可用就使用哪一个。

实现双人聊天
mkfifo 1.fifo   2.fifo创建两个通信管道

read.c :
#include "func.h"
// read 1.pipe读 2.pipe写
int main(int argc,char** argv)
{
        int fdr,fdw;
        fdr=open(argv[1],O_RDONLY);
        fdw=open(argv[2],O_WRONLY);
        printf("fdr=%d,fdw=%d\n",fdr,fdw);
        char buf[20]={0};
        int ret;
        fd_set rdset;  //操作描述符集合
        struct timeval t;
        t.tv_usec=0;
        while(1){
                FD_ZERO(&rdset);
                FD_SET(0,&rdset);   //增加fd stdin
                FD_SET(fdr,&rdset);
                t.tv_sec=3;
                ret=select(fdr+1,&rdset,NULL,NULL,&t);
                if(ret>0){
                        if(FD_ISSET(0,&rdset)){
                                memset(buf,0,sizeof(buf));
                                ret=read(0,buf,sizeof(buf));   //stdin保存到buf
                                if(ret>0){
                                        write(fdw,buf,strlen(buf)-1);   //write buf to管道2写端
                                }else {
                                        printf("bye\n");break;}
                        }
                        if(FD_ISSET(fdr,&rdset)){
                                memset(buf,0,sizeof(buf));
                                ret=read(fdr,buf,sizeof(buf));   //read管道1保存到buf
                                if(ret>0) printf("B:%s\n",buf);
                                else {printf("bye\n"); break;}
                        }
                }

                else printf("no fd can read");
        }
        close(fdr);
        close(fdw);
        return 0;
}
write.c 与其类似,不过需要注意的是:
read.c先打开的1.fifo的read端,那么对应write.c 先打开1.fifo的write端
read.c再打开的2.fifo的write端,那么对应write.c 再打开2.fifo的read端

#include "func.h"
// write 1.pipe写 2.pipe读
int main(int argc,char** argv)
{
        int fdr,fdw;
        fdw=open(argv[1],O_WRONLY); //1.pipe
        fdr=open(argv[2],O_RDONLY);
        printf("fdr=%d,fdw=%d\n",fdr,fdw);

        char buf[20]={0};
        int ret;
        fd_set rdset;  //操作描述符集合
        struct timeval t;
        t.tv_usec=0;
        while(1){
                FD_ZERO(&rdset);
                FD_SET(0,&rdset);   //增加fd stdin
                FD_SET(fdr,&rdset);
                t.tv_sec=3;
                ret=select(fdr+1,&rdset,NULL,NULL,NULL);
                if(ret>0){
                        if(FD_ISSET(0,&rdset)){
                                memset(buf,0,sizeof(buf));
                                ret=read(0,buf,sizeof(buf));   //stdin保存到buf
                                if(ret>0){
                                        write(fdw,buf,strlen(buf)-1);   //write buf to管道2写端
                                }else {
                                        printf("bye\n");break;}
                        }
                        if(FD_ISSET(fdr,&rdset)){
                                memset(buf,0,sizeof(buf));
                                ret=read(fdr,buf,sizeof(buf));   //read管道1保存到buf
                                if(ret>0) printf("A:%s\n",buf);
                                else {printf("bye\n"); break;}
                        }
                }

                else printf("no fd can read");
        }
        close(fdr);
        close(fdw);
        return 0;
}

fun.h内容:
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/mman.h>

2.mmap实现大文件的复制
比cp命令更快,mmap是文件映射入内存,是通过磁盘驱动器硬件实现,不在内核空间与用户空间交换数据。

#include "func.h"
void mmapcopy(int src_fd,int dst_fd,size_t src_len){
        void *src_ptr, *dst_ptr;  
        //将待复制文件、新建文件映射到内存的指针保存下来
        src_ptr = mmap(NULL, src_len, PROT_READ, MAP_PRIVATE, src_fd, 0);  
        dst_ptr = mmap(NULL, src_len, PROT_WRITE | PROT_READ, MAP_SHARED, dst_fd, 0);  
        memcpy(dst_ptr,src_ptr,src_len);
        //解除映射
        munmap(src_ptr,src_len);
        munmap(dst_ptr,src_len);
}
int main(int argc,char **argv){
        int src_fd,dst_fd;
        src_fd=open(argv[1],O_RDONLY);
        dst_fd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
        struct stat filestat;
        stat(argv[1],&filestat);
        ftruncate(dst_fd,filestat.st_size);
        mmapcopy(src_fd,dst_fd,filestat.st_size);

        printf("src_fd=%d,dst_fd=%d\n",src_fd,dst_fd);
        close(src_fd);
        close(dst_fd);
        return 0;
}

3.file_hole
两种产生大文件的方式:

//直接改变文件大小
ftruncate(int fd,off_t length)

//将文件前length全部置0,后面补字符串  
lseek(int fd,off_t length,SEEK_SET)
char *str="cuixuange";
write(fd,str,sizeof(str));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值