例子1 拷贝文件
例子3 读文件
fnctl
读写文件锁
lseek
mmap
umask
stat
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd1 = open("a.txt",O_RDONLY);
if(fd1 == -1) perror("open a"),exit(-1);
int fd2=open("b.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd2 == -1) perror("open b"),exit(-1);
char buf[3] = { };//真正开发时,长度2k或4k
while(1){//如果文件比较大,一次读不完
int res = read(fd1,buf,sizeof(buf));//读a
if(res == -1) { perror("read"); break; }
if(res == 0) { printf("拷贝完毕\n"); break; }
write(fd2,buf,res);//读多少,就写多少
}//多读一次,读的是文件尾,返回0
close(fd1); close(fd2);
}
例子2 打开文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(){
printf("O_CREAT=%d,O_RDONLY=%d,O_WRONLY=%d,"
"O_RDWR=%d,O_APPEND=%d\n",O_CREAT,O_RDONLY,
O_WRONLY,O_RDWR,O_APPEND);
int fd =open("a.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd == -1) perror("open"),exit(-1);
printf("fd=%d\n",fd);
close(fd);
}//"abc""123" == "abc123"
例子3 读文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(){
int fd = open("a.txt",O_RDONLY);
if(fd == -1) perror("open"),exit(-1);
char buf[100] = { };
int res = read(fd,buf,sizeof(buf));
if(res == -1) perror("read"),exit(-1);
printf("读到了%d字节数据,内容:%s\n",res,buf);
close(fd);
}
文件描述符复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd = open("a.txt",O_RDWR);
if(fd == -1) perror("open"),exit(-1);
int fd2 = dup(fd);//只复制描述符,不复制文件表
printf("fd=%d,fd2=%d\n",fd,fd2);
write(fd,"1",1);
write(fd2,"2",1);
int fd3 = dup2(fd,100);
printf("fd3=%d\n",fd3);//100
int fd4 = open("b.txt",O_RDWR|O_CREAT,0666);
printf("fd4=%d\n",fd4);//5
int fd5 = dup2(fd,5);//关闭b.txt,打开a.txt
printf("fd5=%d\n",fd5);//5
write(fd5,"HEHE",4);//共用文件表,在2的后面写
close(fd);//从文件描述符总表删除fd
}
fnctl
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd=open("a.txt",O_RDONLY|O_CREAT|O_APPEND,
0666);
if(fd == -1) perror("open"),exit(-1);
int flags = fcntl(fd,F_GETFL);//取不到O_CREAT
printf("flags=%d\n",flags);
//验证某一位二进制是0还是1,用 位与& 运算
if(flags & O_CREAT) printf("CREATE\n");
if(flags & O_APPEND) printf("APPEND\n");
//权限比较用后两位,如何取后2位,与3位与
if((flags&3)== O_RDWR) printf("RDWR\n");
if((flags&3)== O_RDONLY) printf("RDONLY\n");
printf("------------------\n");
fcntl(fd,F_SETFL,O_RDWR);//设置,只有APPEND能改
flags = fcntl(fd,F_GETFL);//取出新的状态
if(flags & O_APPEND) printf("APPEND\n");
if((flags&3)== O_RDWR) printf("RDWR\n");
if((flags&3)== O_RDONLY) printf("RDONLY\n");
close(fd);
}
读写文件锁
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd = open("a.txt",O_RDWR);
if(fd == -1) perror("open"),exit(-1);
struct flock lock;
lock.l_type = F_RDLCK;//读锁 写锁是F_WRLCK
lock.l_whence = SEEK_SET;//从头开始最简单
lock.l_start = 0;//从文件的第一个字节开始锁定
lock.l_len = 20;//锁定20个字节
lock.l_pid = -1;//SETLK用不到这个参数,-1即可
int res = fcntl(fd,F_SETLK,&lock);//上锁
if(res == -1) perror("上锁失败\n"),exit(-1);
else printf("成功了\n");
sleep(20);
printf("读文件完成了,释放读锁\n");
lock.l_type = F_UNLCK;
fcntl(fd,F_SETLK,&lock);//释放锁的代码
sleep(20);
printf("其他代码也完毕,程序结束\n");
close(fd);
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd = open("a.txt",O_RDWR|O_TRUNC);
if(fd == -1) perror("open"),exit(-1);
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET; lock.l_start = 0;
lock.l_len = 10; lock.l_pid = -1;
int res = fcntl(fd,F_SETLKW,&lock);
if(res == -1){
printf("有进程在使用,无法写文件\n");
}else{
res = write(fd,"hello",5);//写文件前先加写锁
if(res == -1) perror("write"),exit(-1);
else printf("写入成功\n");
}
close(fd);
}
lseek
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(){
int fd = open("a.txt",O_RDWR);
if(fd == -1) perror("open"),exit(-1);
char ch;
read(fd,&ch,1); printf("%c\n",ch);//a
read(fd,&ch,1); printf("%c\n",ch);//b
lseek(fd,3,SEEK_CUR);
read(fd,&ch,1); printf("%c\n",ch);//f
lseek(fd,0,SEEK_SET);//回到开始
write(fd,"1",1);//a
lseek(fd,3,SEEK_SET); write(fd,"2",1);//d
lseek(fd,2,SEEK_CUR); write(fd,"3",1);//g
lseek(fd,-2,SEEK_CUR); write(fd,"4",1);//f
lseek(fd,-3,SEEK_END); write(fd,"5",1);//s
close(fd);
}
mmap
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
struct Emp{
int id;
char name[20];
double sal;
};
int main(){
int fd=open("em.dat",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd == -1) perror("open"),exit(-1);
void* p = mmap(0,sizeof(struct Emp)*3,
PROT_READ|PROT_WRITE,
//MAP_SHARED,//数据存入文件
MAP_PRIVATE,//数据不存入文件
fd,0);
if(p == MAP_FAILED) perror("mmap"),exit(-1);
ftruncate(fd,sizeof(struct Emp)*3);//指定大小
struct Emp* pe = p;//数据在文件中
pe[0].id = 100; strcpy(pe[0].name,"zhangfei");
pe[0].sal = 12000.0;
pe[1].id = 200; strcpy(pe[1].name,"guanyu");
pe[1].sal = 20000.0;
pe[2].id = 300; strcpy(pe[2].name,"liubei");
pe[2].sal = 24000.0;
int i;
for(i=0;i<3;i++)
printf("%d,%s,%lf\n",pe[i].id,pe[i].name,
pe[i].sal);
close(fd);
}
打印目录
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
void print(char* path){//把代码写一下
DIR* dir = opendir(path);
if(dir == NULL) return;//结束递归但不结束进程
struct dirent* ent;
while(ent=readdir(dir)){//先read,后赋值,再判断
if((strcmp(ent->d_name,".")==0) ||
(strcmp(ent->d_name,"..")==0)) continue;
if(ent->d_type == 4){//子项是目录
printf("[%s]\n",ent->d_name);//dname不包括路径
char buf[100] = {};
sprintf(buf,"%s/%s",path,ent->d_name);
print(buf);//递归调用打印子目录
}else{//子项是 文件
printf("%s\n",ent->d_name);
}
}
}
int main(){
print("../");
//显示UC目录下的所有子项,子目录的内容也要显示出来
//思路:先读UC目录的子项,如果子项是目录,打印出来
//然后递归调用print(),如果子项是文件,直接打印
}
umask
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){//了解即可
int fd1 = open("aa",O_RDWR|O_CREAT,0666);//664
mode_t old = umask(0022);//属主不屏蔽,其他屏蔽2
int fd2 = open("bb",O_RDWR|O_CREAT,0666);//644
umask(old);//还原成系统默认屏蔽
int fd3 = open("cc",O_RDWR|O_CREAT,0666);//664
close(fd1); close(fd2); close(fd3);
}
stat
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
//取文件大小必须会
int main(){
struct stat s = {};
int res = stat("a.txt",&s);
if(res == -1) perror("stat"),exit(-1);
printf("获取硬盘文件的属性成功\n");
printf("inode=%d\n",s.st_ino);
printf("size=%d\n",s.st_size);
printf("nlink=%d\n",s.st_nlink);
printf("tm=%s\n",ctime(&s.st_mtime));//转英文日期
printf("mode=%o\n",s.st_mode);
printf("权限:%o\n",s.st_mode & 07777);//取后4位
if(S_ISREG(s.st_mode)) //系统提供宏函数判断类型
printf("普通文件\n");
if(S_ISDIR(s.st_mode))
printf("目录\n");
}