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)做了必要的优化,内部维护一个缓冲区,只有在满足特定条件时才将缓冲区与系统内核同步,借此降低
执行系统调用的频率,减少进程在用户态和进程态之间来回切换的次数,提高运行性能。