1、设备或文件操作两种方式:
1)用户编程接口 API
2)系统调用
2、文件描述符fd
1)每个进程PCB结构中有文件描述符指针,指向files_struct的文件描述符表,记录每个进程打开的文件列表
2)系统内核不允许应用程序访问进程的文件描述符表,只返回这些结构的索引即文件描述符ID(File Description)给应用程序
3)Linux系统中,应用程序通过这些文件描述符来实现让内核对文件的访问
3、特殊文件描述符号
标准输入STDIN_FILENO
标准输出STDOUT_FILENO
标准错误STDERR_FILENO
每个进程被加载后,默认打开0,1,2这三个文件描述符
4、open、close、read、write、lseek函数用法实例
//程序1
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv[])
{
int fd;//定义文件描述符
char buf[1024] = "hello world!";
char buf1[1024];
int len;
if (argc < 2)
{
printf("filname\n");
exit(1);
}
//创建或打开一个文件
fd=open(argv[1],O_CREAT | O_RDWR,0644);
//写数据到文件
write(fd,buf,strlen(buf));
//写完数据后应关闭文件再打开读取,否则可能无法读取到数据。
close(fd);
fd=open(argv[1],O_RDWR);
//阻塞读
printf("fd=%d\n",fd);//输出文件描述符
printf("lensizeof(buf1)=%d\n",sizeof(buf1));//计算字符数组大小
memset(buf1,0,sizeof(buf1));//清空缓存区
len=read(fd,buf1,sizeof(buf1));//从fd复制到缓冲区中的字节数
printf("len=%d\n",len);
//将数据显示在终端
write(STDOUT_FILENO,buf1,len);
printf("\nfd=%d\n",fd);
close(fd);
return 0;
}
//程序2
#include
#include
#include
#include
#include
#include
int main(void)
{
//以可读可写方式打开程序1创建的文件
int fd=open("first.h",O_RDWR);
if(fd<0)
{
perror("open first.h");
exit(1);
} //0x1000=4096k
lseek(fd,0x1000,SEEK_SET);//文件重定位,偏移文件开头0x1000
write(fd,"a",1);//并写入数据a
close(fd);//关闭文件
}
程序1和程序2配套使用,终端命令具体执行如下图示:
对打开文件,关闭文件,读取文件,设置文件锁,解文件锁的封装函数设计
//程序3
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct flock lock;//定义结构体类型变量
//打开一个文件,参数(文件名称,打开方式)
int File_open(char *pcName, int flag)
{
int fd;//定义文件描述符
//创建或打开一个文件
fd = open(pcName, flag);
if (fd == -1)//打开失败
{
perror("open file\n");
exit(-1);
}
else//打开成功
{
printf("success to open file\n");
}
return fd;//返回文件描述符
}
//关闭一个文件,参数(文件描述符)
int File_close(int fd)
{
int filefd;//定义文件描述符
//关闭文件
filefd = close(fd);
if (filefd == -1)//关闭失败
{
perror("close file\n");
exit(-1);
}
else//关闭成功
{
printf("success to close file\n");
}
return filefd;//返回文件描述符
}
//从文件读取数据(文件描述符,缓冲区,缓冲区大小)
int File_read(int fd,char *buf,int bufferlen)
{
int len;//从文件中读取的字节数
int file_fd=fd;//文件描述符
printf("bufferlen=%d\n",bufferlen);
//读取数据后返回读取到的字节数
len=read(file_fd,buf,bufferlen);
if(len==-1)
{
perror("read file\n");
}
else
{
printf("已读取的字节数len=%d\n",len);
//终端显示读取到的数据
write(STDOUT_FILENO,buf,len);
printf("\n");
}
return len;//返回读取到的字节数
}
//设置文件锁(文件描述符)
int File_lock(int fd)
{
int state;//文件锁状态返回值
//获得锁信息
state=fcntl(fd,F_GETLK,&lock);
if(state<0)
{
perror("get file lock state\n");
return -1;
}
else//获得锁调用成功
{
printf("设置之前文件锁类型:%d\n",lock.l_type);
if (lock.l_type != F_UNLCK)//文件锁已设置
{
printf("文件锁不能被设置! \n");
return -1;
}
if(lock.l_type == F_UNLCK)//文件锁为空
{
printf("文件锁可以设置! \n");
lock.l_type = F_WRLCK;//设置排他锁
//设置文件锁
state=fcntl(fd,F_SETLK,&lock);
if (state == -1)
{
printf("设置失败!\n");
return -1;
}
else//设置排他锁成功
{
printf("设置之后文件锁类型:%d\n",lock.l_type);
printf("设置成功!\n");
return 0;
}
}
}
}
//解文件锁(文件描述符)
int File_unlock(int fd)
{
int state;//文件锁状态返回值
printf("获取状态之前设置之前文件锁类型:%d\n",lock.l_type);
//获得锁信息
state=fcntl(fd,F_GETLK,&lock);
if(state==-1)
{
perror("get file lock state\n");
return -1;
}
else//获得锁调用成功
{
printf("设置之前文件锁类型:%d\n",lock.l_type);
if (lock.l_type != F_UNLCK)//文件锁为解锁状态
{
printf("文件锁不能被解锁\n");
return -1;
}
else//文件锁已设置
{
printf("文件锁可以设置\n");
lock.l_type = F_UNLCK;//定义锁类型为解锁
//解锁
state=fcntl(fd,F_SETLK,&lock);
if (state == -1)
{
printf("设置失败!\n");
return -1;
}
else//解锁调用成功
{
printf("设置之后文件锁类型:%d\n",lock.l_type);
printf("设置成功!\n");
return 0;
}
}
}
}
//主函数
int main(void)
{
int file_fd;//定义文件描述符
int i;//关闭文件标志位
int j=0;//文件中读取的字节数
int k=2;//文件锁状态返回值
char buf[50];//读取数据缓存数组
int buf_len;//缓存数组大小
memset(&lock, 0, sizeof(struct flock));//结构体清零
//l_whence有SEEK_SET、SEEK_CUR和SEEK_END。
lock.l_whence = 0;//偏移量的起始位置:文件开始处
lock.l_start = SEEK_SET;//l_whence的偏移量:从文件开始处计算偏移
lock.l_len = 0;//表示从起点开始直至最大可能位置为止。
//打开文件
file_fd = File_open("hello.c", O_CREAT | O_RDWR);
if (file_fd == -1)//打开失败
{
perror("open file\n");
}
else//打开成功,输出文件描述符
{
printf("文件打开成功fd=%d\n", file_fd);
printf("\n");
}
//读文件
memset(buf,0,sizeof(buf));//清空字符数组数据
buf_len=sizeof(buf);//计算字符数组大小
j=File_read(file_fd,buf,buf_len);
if(j==-1)
{
printf("读取文件失败!\n");
}
else
{
printf("读取文件成功!\n");
printf("从文件中读取的字节数=%d\n",j);
printf("\n");
}
//设置文件锁
k=File_lock(file_fd);
if(k==-1)
{
printf("设置文件锁失败!\n");
}
else
{
printf("文件锁状态返回值k=%d\n",k);
printf("文件锁设置成功!\n");
printf("\n");
}
//解文件锁
k=File_unlock(file_fd);
if(k==-1)
{
printf("解锁失败!\n");
printf("\n");
}
else
{
printf("文件锁状态返回值k=%d\n",k);
printf("解锁成功!\n");
printf("\n");
}
//关闭文件
i = File_close(file_fd);
if (i == -1)//关闭失败
{
printf("关闭文件失败!\n");
}
else//关闭成功
{
printf("关闭文件 %d 成功\n", i);
printf("\n");
}
return 0;
}
注:
当文件加锁后,状态位由1--变为0,其他程序需要检测到该文件状态位为0时,无法访问该文件,直到状态位为1时。
文件解锁,状态位由0++变为1。
程序执行效果: