高级IO的其他函数

1.readv和writev

	NAME
	readv, writev, preadv, pwritev - read or write data into 
	multiple buffers
	
	SYNOPSIS
	#include <sys/uio.h>
	
	ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
	
	ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

读写多个非连续缓冲区,也称为散布读和聚集写
第二个参数是一个指向iovec结构数组的一个指针

   struct iovec {
    
    
     void  *iov_base;    /* Starting address */
     size_t iov_len;     /* Number of bytes to transfer */
 };

第三个参数是有几个这样的结构体数组

2.mmap

NAME
       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS
       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

addr用于指示映射存储区的起始地址,通常设置为0,由系统进行选择,返回值是映射区的起始地址。
fd是要被映射的文件描述符
length是要映射的字节数
offset是要映射字节在文件中的偏移量
prot制定了映射存储区的保护要求
flag参数影响映射存储区的多重属性

3.内存映射demo

int main(int argc, char **argv)
{
    
    
    int fd;
    size_t len;
    off_t off;
    struct stat statres;
    char *pStr;
    int i, count = 0;

    if(argc < 2)
    {
    
    
            fprintf(stderr,"argc \n");
            exit(1);
    }

    fd = open(argv[1],O_RDONLY );
    if(fd < 0)
    {
    
    
            perror("open()");
            exit(1);
    }
	//获取文件状态
    if(fstat(fd, &statres) < 0)
    {
    
    
            perror("fstat()");
            exit(1);
    }


	//映射成一个大字符串
    pStr = mmap(0, statres.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if(MAP_FAILED == pStr)
    {
    
    
            perror("mmap()");
            exit(1);
    }
	//关闭文件描述符
    close(fd);

    for(i = 0; i < statres.st_size; i++)
            if('a' == pStr[i])
                    count++;

    printf("%d\n", count);
	//解除映射
    munmap(pStr, statres.st_size);



    return 0;
}

实现查询一个文件中字符a的个数

匿名映射

通过使用我们发现,使用映射区来完成文件读写操作十分方便,父子进程间通信也较容易。但缺陷是,每次创建映射区一定要依赖一个文件才能实现。通常为了建立映射区要open一个temp文件,创建好了再unlink、close掉,比较麻烦。 可以直接使用匿名映射来代替。其实Linux系统给我们提供了创建匿名映射区的方法,无需依赖一个文件即可创建映射区。同样需要借助标志位参数flags来指定:MAP_ANONYMOUS (或MAP_ANON)。
如:int *p = mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

4.mmap实现共享内存

先mmap然后在fork,这样子进程也有一份


#define SIZE 1024

int main(int argc, char **argv)
{
    
    
    pid_t pid;
    char *p;

	//子进程写 父进程读 共享 匿名 -1不需要文件描述符
    p = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, 
    MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    if(MAP_FAILED == p)
    {
    
    
            perror("mmap()");
            exit(1);
    }


    pid = fork();
    if(pid < 0)
    {
    
    
            munmap(p, SIZE);
            perror("fork()");
            exit(1);
    }

    if(0 == pid)
    {
    
    
    		//子进程对共享内存进行写入
            strcpy(p, "Hello");
    }
    else
    {
    
    
    	//等待子进程完成
            wait(NULL);
            puts(p);
    }

    munmap(p, SIZE);



    return 0;
}

猜你喜欢

转载自blog.csdn.net/ZZHinclude/article/details/119863925