c(3)内存映射+文件操作系统函数

1)内存映射

//01mmap.c

//内存映射的建立与解除
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
int main(){
    char *p=(char*)mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE,\
            -1,0);//最后一个参数是4096的整数倍
    if(p==MAP_FAILED){
        perror("mmap");
        exit(EXIT_FAILURE);
    }
    strcpy(p,"Hello,Memory!");
    printf("%s\n",p);
    if(munmap(p,4096)==-1){
        perror("munmap");
        exit(EXIT_FAILURE);
    }
    strcpy(p+=4096,"Hello,Memory!");
    printf("%s\n",p);
    if(munmap(p,4096)==-1){
        perror("munmap");
        exit(EXIT_FAILURE);
    }
        return 0;
}

输出:

Hello,Memory!
Hello,Memory!

2)文件操作

i)w文件打开关闭、读写

<unistd.h>
long sysconf(int name);
ssize_t write(int fd, const void *buf, size_t count);
[write:向文件描述符fd所引用的文件中写入从buf开始的缓冲区中count
字节的数据.POSIX规定,当使用了write()之后再使用read(),那么读取到的
应该是更新后的数据.但请注意并不是所有的文件系统都是 POSIX兼容的.
返回值:
成功时返回所写入的字节数(若为零则表示没有写入数据).
错误时返回-1,并置errno为相应值.
若count为零,对于普通文件无任何影响,但对特殊文件 将产生不可预料的后果.]
<string.h>

size_t strlen(const char *s);

//02open.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main(){
    //获取一个进程最多持有多少个处于打开状态的文件描述符,由limit.h
    //头文件中的_SC_OPEN_MAX宏决定,合法文件描述符值为0~(OPEN_MAC)决定
    long openmax=sysconf(_SC_OPEN_MAX);
    printf("一个进程最多能持有%ld个处于打开状态的文件描述符\n",openmax);
    //1)写文件
    int fd=open("open.txt",O_RDWR|O_CREAT|O_TRUNC,0666);//O_CREAT:不存在则创建;O_TRUNC存在即清空。权限为0666
    if(fd==-1){
        perror("open");
        exit(EXIT_FAILURE);
    }
    char text[]="将这些内容写入到文件中";
    if((write(fd,text,strlen(text)))==-1){ //写入到open.txt文件中
        perror("write");
        exit(EXIT_FAILURE);
    }
    if(close(fd)==-1){
        perror("close");
        exit(EXIT_FAILURE);
    }
    //2)读文件
    fd=open("open.txt",O_RDONLY,0444);
    if(fd==-1){
        perror("open");
        exit(EXIT_FAILURE);
    }
    char text1[1024]={};
    if((read(fd,text1,1024))==-1){//读取
        perror("read");
        exit(EXIT_FAILURE);
    }
    printf("%s\n",text1);
    if(close(fd)==-1){
        perror("close");
        exit(EXIT_FAILURE);
    }
    return 0;
}
输出:
一个进程最多能持有1024个处于打开状态的文件描述符
将这些内容写入到文件中

ii)I/O重定向

//03io.c
#include <stdio.h>
#include <string.h>
int main(){
    char buf[1024];
    scanf("%s",buf);
    printf("%s\n",buf);
    strcpy(buf,"标准输出已被I/O重定向为输出到文件o.txt.");
    printf("%s\n",buf);
    return 0;
}
得到a.out后,控制台输入:
./a.out 0<i.txt 1>o.txt
0<i.txt为关闭文件描述符0,打开i.txt,该文件获得文件描述符0,即代码中的scanf函数从i.txt文件中输入内容;
1>o.txt为关闭文件描述符1,打开o.txt,该文件获得文件描述符1,即代码中的print函数将内容输出到o.txt文件
已经创建好的i.txt里的内容为:1234567890
则执行上步操作后,得到的o.txt里内容为:
1234567890
标准输出已被I/O重定向为输出到文件o.txt.


iii)读写格式

基于系统调用的文件读写本来就是面向二进制字节流的,因此二进制读写无需做任何额外的工作
对于写入内容的格式化和对读取内容的解格式化,要在write前加上sprintf,read后加上fscanf
(写入读出结构体时使用更为合适,例
sprintf(buf,"%s %d %0.2f",emp.name,emp.age,emp.salary);
sscanf(buf,"%s%d%f",emp,name,&emp.age,&emp.salary);)

iv)系统调用和标准库调用

当系统调用函数(open/close,write/read)被执行时,需要在用户态和内核态之间来回切换,因此频繁调用执行系统会严重影响性能(控制台输[time 可执行文件名]查看程序运行时间)
而标准库(fopen/fclose,fwrite/fread)做了必要的优化,内部维护一个缓冲区,只有在满足特定条件时才将缓冲区与系统内核同步,借此降低
执行系统调用的频率,减少进程在用户态和进程态之间来回切换的次数,提高运行性能。



猜你喜欢

转载自blog.csdn.net/mengbabe_2018/article/details/80469508
今日推荐