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));