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