一:系统I/O函数
1.open函数
【原型】 int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
【功能】 打开一个指定的文件并获得文件描述符,或者创建一个新文件。
【头文件】 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
【参数flags】 O_RDONLY :只读方式打开文件
O_WRONLY :只写方式打开文件
O_RDWR :读写方式打开文件
O_CREAT :如果文件不存在,则创建该文件
O_EXCL :如果使用O_CREAT选项且文件存在,则返回错误消息。
O_NOCTTY :如果文件为终端,那么终端不可作为调用open()系统调用的那个进程的控制终端。
O_TRUNC :如果文件已经存在,则删除文件中原有数据。
O_APPEND :以追加方式打开文件。
【参数mode】 如果文件被新建,指定其权限为mode(八进制表示法)
【返回值】 成功:返回>=0 的整数(即文件描述符) 失败 -1
【使用需要注意问题】
1. flags 的各种取值可以用 位或 的方式叠加起来。
比如:读写方式打开,不存在要新建,如果存在了则清空它 ---> O_RDWR | O_CREAT | O_TRUNC
2.mode 是八进制权限,比如0644, 或者0755等
3. open函数可以用来打开普通文件、块设备文件、字符设备文件、链接文件和管道文件
但只能用来创建普通文件,每一种特殊文件的创建都有其特定的函数。
4. 其返回值就是一个代表这个文件的描述符,是一个非负整数,这个整数将作为以后任何系统IO函数对其操作的句柄,或称入口。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc,const **argv)
{
int fd1,fd2,fd3,fd4,fd5;
fd1 = open("./1.txt",O_RDONLY);
fd2 = open("./2.txt",O_RDWR|O_CREAT);
fd3 = open("./3.txt",O_RDWR|O_CREAT|O_EXCL);
fd4 = open("./1.txt",O_WRONLY);
fd5 = open("./1.txt",O_RDONLY);
printf("%d\n",fd1);
printf("%d\n",fd2);
printf("%d\n",fd3);
printf("%d\n",fd4);
printf("%d\n",fd5);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
2.close函数
【原型 】 int close(int fd);
【功能 】 关闭文件并释放相应的资源。
【头文件】 #include<unistd.h>
【参数fd】 即将要关闭的文件描述符
【返回值】 成功 0 失败 -1
【备注】 重复关闭一个已经关闭了的文件或者尚未打开的文件是安全的。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,const **argv)
{
int fd1,fd2,n1,n2,n3;
fd1 = open("./1.txt",O_RDONLY);
fd2 = open("./2.txt",O_RDWR|O_CREAT);
printf("%d\n",fd1);
printf("%d\n",fd2);
n1 = close(3);
n2 = close(4);
n3 = close(20);
printf("%d\n",n1);
printf("%d\n",n2);
printf("%d\n",n3);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
3.read函数
【原型】 ssize_t read(int fd void *buf,size_t count);
【功能】 从指定文件中读取数据
【头文件】 #include <unistd.h>
【参数fd】 从文件fd中读取数据
【参数buf】 指向存放读读取的字节数
【参数count】想要从文件fd中读取的字节数
【返回值】 成功:实际读到的字节数 失败 -1
【备注】 实际读到的字节数小于count
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,const **argv)
{
int fd1,n1,i;
char buf[100];
fd1 = open("./1.txt",O_RDONLY);
printf("%d\n",fd1);
n1=read(3,buf,100);
printf("%d\n",n1);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
4.write函数
【原型】 ssize_t write(int fd,const void *buf,size_t count);
【功能】 将数据写入指定的文件
【头文件】 #include <unistd.h>
【参数fd】 将数据写入到文件fd中
【参数buf】 指向即将要写入的数据
【参数count】要写入的字节数
【返回】 成功:实际写入的字节数 失败:-1
【备注】 实际写入的字节数小于等于count
【注意】
1. 实际读写的字节数要通过返回值来判断,参数count只是一个"愿望值";
2. 当实际的读写字节数小于count 时,有以下几种情形:
A)读操作时,文件剩余可读字节数不足count
B)读写操作期间,进程收到异步信号
3. 读写操作同时对f_pos起作用。也就是说,不管是读还是写,文件的位置偏移量(即内核中的f_pos)都会
加上实际读写的字节数,不断的往后偏移。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,const **argv)
{
int fd1,n1;
char buf[20]="abacfjd";
fd1 = open("./2.txt",O_WRONLY);
printf("%d\n",fd1);
n1=write(3,buf,20);
printf("%d\n",n1);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
5.lseek函数
【原型】 off_lseek(int fd,off_t offset, int whence);
【功能】调整文件位置偏移量
【头文件】 #include <sys/types.h>,#include <unistd.h>
【参数fd】 要调整位置偏移量的文件的描述符。
【参数offset】 新位置偏移量相对基准点
【参数whence】基准点:SEEK_SET:文件开头处
SEEK_CUR:当前位置
SEEK_END:文件末尾处
【返回值】 成功: 新文件位置偏移量 失败 -1
【注意要点】
1.lseek() 只对普通文件奏效,特殊文件时无法调整偏移量的。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,const **argv)
{
int fd;
fd = open("./2.txt",O_RDWR);
printf("%d\n",fd);
lseek(fd,-1,SEEK_SET);
write(fd,"1",1);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
6.dup函数
【原型】 int dup(int oldfd);
【功能】 复制文件描述符
【头文件】 #include<unistd.h>
【参数oldfd】要复制的文件描述符
【返回值】 成功:新的文件描述符 失败 -1
7.dup2函数
【原型】 int dup2(int oldfd,int newfd);
【功能】 复制文件描述符
【头文件】 #include<unistd.h>
【参数oldfd】 要复制的文件描述符
【参数newfd】 指定的新文件描述符
【返回值】 成功:新文件描述符 失败 -1
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,const **argv)
{
int fd,newfd,newfd1;
fd = open("./2.txt",O_RDWR);
printf("%d\n",fd);
newfd = dup(3);
printf("%d\n",newfd);
newfd1 = dup2(3,100);
printf("%d\n",newfd1);
write(3,"222222",6);
return 0;
}
-----------------------------------------------------------------------------------------------------------------------
8.ioctl函数
【原型】 int ioctl(int d,int request,...);
【功能】 文件控制
【头文件】 #include <sys/ioctl.h>
【参数d】 要控制的文件描述符
【参数request】 针对不同文件的各种控制命令字
【变参】 根据不同的命令而不同
【返回值】 成功:一般情况下是0,但有些特定的请求将返回非负整数。 失败 -1
9.fcntl函数
【原型】 int fcntl(int fd,int cmd,...);
【功能】 文件控制
【头文件】 #include<unistd.h>,#include <fcntl.h>
【参数fd】 要控制的文件描述符
【参数cmd】 控制命令字
【变参】 根据不同的命令而不同。
【返回值】 成功: 根据不同的cmd ,返回值不同。 失败 -1
10.mmap函数
【原型】 void *mmap(void *addr,size_t length,int prot,int flags, int fd,off_t offset);
【功能】 内存映射
【头文件】 #include <sys/mman.h>
【参数addr】 映射内存的起始地址。
如果该参数为NULL,则系统会自动寻找一个合适的起始地址,一般都使用这个值。
如果该参数不为NULL,则系统会以此为依据来找到一个合适的起始地址,在Linux中,映射后的内存起始地址必须是页地址的整数倍。
【参数length】 映射内存大小。
【参数prot】 映射内存的保护权限。PROT_EXEC :可执行
PROT_READ :可读。
PROT_WRITE :可写
PROT_NONE :不可访问。
【参数flag】 以下两个选项互斥:
1.MAP_SHARED:所有的同时映射了这块内存的进程对数据的变更均可见,而且数据的变更会直接同步到对应的文件
有时可能还需要调用mync()或者munmap()才会真正起作用。
2.MAP_PRIVATE :与MAP_SHARED相反,映射了这块内存的进程对数据的变更对别的进程不可见,也不会影响其对应的文件数据。
以下选项可以位或累加:
1.MAP_32BIT :在早期的64位x86处理器上,设置这个选项可以将线程的栈空间设置在最低的2GB空间附近
2.MAP_ANONYMOUS :匿名映射,该选项使得该映射内存不与任何文件关联,一般来讲参数fd和offset会被忽略(但是可移植性程序需要
将fd设置为-1),另外,这个选项必须跟MAP_SHARED 一起使用。
3.MAP_DENYWRITE :很久以前,这个选项可以使得试图写文件fd的进程收到一个ETXTBUSY的错误
但是这很快成为所谓"拒绝服务"攻击的来源。
4.MAP_FIXED :该选项使得映射内存的起始地址严格等于参数addr而由于可移植性的关系,这个选项一般不建议设置。
5.MAP_GROWSDOWN :使得映射内存向下增长,即返回的是内存的最高地址,一般用于栈。
6.MAP_HUGETLB:使用"大页"来分配映射内存,关于"大页",请参考内核源代码中的Documentation/vm/hugetlbpage.txt.
7.MAP_NONBLOCK :该选项必须与MAP_POPULATE 一起使用,表示不进行"预读"操作,这使得选项MAP_POPULATE变得毫无意义。
8.MAP_NORESERVE: 该选项是不为这块内存使用“交换分区”,也就是说当物理内存不足时,操作映射内存将会受到SIGSEGV,
而如果允许使用交换分区则可以保证不会因为物理内存不足而出现这个错误。
9.MAP_POPULATE: 将页表映射至内存中,如果用于文件映射,该选项会导致预读的操作,因而在遇到页错误的时候也不会被阻塞。
10.MAP——STACK :在进程或线程的栈中映射内存。
11.MAP_UNINITIALIZED :不初始化匿名映射内存。
【参数fd】 要映射的文件的描述符
【参数offset】文件映射的开始区域偏移量,该值必须是页内存大小的整数倍,即必须是函数sysconf(_SC_PAGE_SIZE)返回的整数倍。
【返回值】 成功: 映射内存的起始地址。 失败 (void*) -1;
11. memcpy函数
【原型】 void *memcpy(void *dest, const void *src , size_t n);
【功能】 从src地址指向的数据上拷贝n个字节到目标地址dest指向的空间上
【头文件】 #include <string.h>
【参数】 dest:目标地址
src:原有数据的地址
n:拷贝的字节数
【返回值】成功:指向目标地址上基地址的指针 失败:NULL
代码演示:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
int main(int argc,const **argv)
{
int lcd = open("/dev/fb0",O_RDWR);
if(lcd < 0)
{
printf("open lcd error!\n");
return 0;
}
int *FB = NULL;
FB = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
int color = 0x00FF0000;
int i;
for(i=0;i<800*480;i++)
{
memcpy(FB+i,&color,4);
}
munmap(FB,800*480*4);
close(lcd);
return 0;
}
系统I/O函数部分功能的实现:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
char *FileType(char *argv)
{
struct stat info;
stat(argv,&info);
if(S_ISDIR(info.st_mode))
{
printf("这是一个目录!\n");
return "DIR";
}
else if(S_ISREG(info.st_mode))
{
printf("这是一个普通文件!\n");
return "REG";
}
else if(S_ISFIFO(info.st_mode))
{
printf("这是一个管道文件!\n");
return "FIFO";
}
else if(S_ISLNK(info.st_mode))
{
printf("这是一个链接文件!\n");
return "LNK";
}
}
char *Dir(char *argv)
{
DIR *dp = opendir(argv);
struct dirent *ep = NULL;
while(1)
{
ep = readdir(dp);
if(ep == NULL)
break;
printf("%d :",(int)ep->d_off);
printf("%s\n",ep->d_name);
}
rewinddir(dp);
chdir(argv);
system("pwd");
return NULL;
}
char *Read(char *argv,char *buf,int size)
{
int fd = open(argv,O_RDWR);
printf("%s\n",argv);
read(fd,buf,size);
printf("%s\n",buf);
close(fd);
return NULL;
}
char *Write(char *argv,char *buf,int size)
{
int fd = open(argv,O_RDWR);
printf("%s\n",argv);
write(fd,buf,size);
close(fd);
return NULL;
}
int main(int argc,char **argv)
{
char arg[20] = {0};
char ch2[20] = {0};
char buf1[100]={0};
char *buf2="abcdefghijklmn";
while(1)
{
printf("请输入要查找的目录: ");
scanf("%s",arg);
char *arg1 = FileType(arg);
if(strcmp(arg1,"DIR")==0)
{
Dir(arg);
}
if(strcmp(arg1,"REG")==0)
{
Read(arg,buf1,100);
Write(arg,buf2,sizeof(buf2));
}
}
return 0;
}