您的位置:首页 > 运维架构 > Linux

linux文件操作

2017-07-23 14:11 169 查看

一、linux几个目录

1. /bin 用于储存普通用户可执行的命令,如ls,cp

2. /boot linux内核及启动系统是所需要的文件,保证启动文件安全

3. /dev 设备文件的储存目录,如硬盘,光驱(更体现一切皆文件)

4. /etc 用于存放系统的配置文件,比如账户密码

5. /home 普通用户主目录

6. /lib 用于存放各种库文件

7. /proc 该目录是一个虚拟文件系统,只有在系统运行时才存在。可以获取系统的状态信息并且修改某些系统的配置信息。cat/proc/memifo可以获取系统内存的使用状态

8. /sbin是用来存放用于管理系统的命令

9. /tmp 临时文件目录

10. /usr 用于存放系统应用程序及相关文件,如说明文档,帮助文档

11. /var用于存放系统中经常变化的文件,如日志文件,用户邮件

二、文件系统模型

物理磁盘的访问都是通过设备驱动程序进行的。对设备驱动的访问有两种途径:1、通过设备驱动本身提供的接口 2、通过虚拟文件系统提供给上层应用程序的接口(与proc相同,都是只存在与内存而不存在与磁盘之中)

三、文件访问权限

1.r=4,w=2,x=1

2.
int chmod(const char *path,mode_t mode)
int fchmod(intflides,mode_t mode)

头文件是
#include<sys/types.h>
#include<sys/sta.h>


3.mode的参数

参数八进制含义
S_IRUSR(S_IREAD)0400文件所有者具可读
S_IWUSR(S_IWRITE)0200文件所有者具可写入权限
S_IXUSR(S_IEXEC)00100文件所有者具可执行权限
S_IRGRP00040用户组具可读取权限
S_IWGRP00020用户组具可写入权限
S_IXGRP00010用户组具可执行权限
S_IROTH00004其他用户具可读取权限
S_IWOTH00002其他用户具可写入权限
S_IXOTH00001其他用户具可执行权限
my_chmod.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>

int main(int argc,char **argv)
{
int mode;
int mode_u;
int mode_g;
int mode_o;
char *path;

if(argc<3)//保证和命令chmod的参数相同
{
printf("%s <mode num> <target file>\n",argv[0]);
exit(0);
}
mode=atoi(argv[1]);//这里默认你现在获得的参数就是8进制
if(mode>777||mode<0)//保证输入在范围之内
{
printf("mode num error\n");
exit(0);
}
mode_u=mode/100;//求出各个位数
mode_g=(mode-(mode_u*100))/10;
mode_o=mode-(mode_u*100)-(mode_g*10);
mode=(mode_u*8*8)+mode_g*8+mode_o;//这里是8进制转换为十进制
path=argv[2];//实际就是将字符串首地址给了path
if(chmod(path,mode)==-1)//chmod会认为你输入就是10进制,内部会处理,所以这个chmod程序只能说是一个简化
{
perror("chmod errorr");//输出错误信息
//perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)
exit(1);
}
return 0;

}


四、文件打开和关闭

1、open函数

#include<sys/types.h>
#include<sys/stat.h> #include<fcntl.h>
int open(const char *pathname,int flags)
int open(const char *pathname,int flags,mode_t mode);
//具体用哪一个,是由参数flags决定


2.creat函数

int creat(const char *pathname,mode_t mode);

creat只能以只写的方式打开创建的文件

3.close函数

int clode(int fd)

- 成功调用返回一个文件描述符号,否则返回-1

my_creat.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>

int main()
{
int fd;

if((fd=open("example_62.c",O_CREAT|O_EXCL,S_IRUSR|S_IWUSR))==-1)
// if((fd=creat("example_62.c",S_IRWXU))==-1)
{
perror("open");
// printf("open:%s   with errno:%d\n",strerror(errno),errno);/;/strerror会把错误以字符串形式输出,errno是全局变量对应数字是错误
exit(1);
}
else
{
printf("create file success!\n");
}
close(fd);
return 0;
}


mode参数含义
O_RDONLY只读打开
O_WRONLY只写打开
O_RDWR读写打开
O_SEARCH(仅对目录有意义)只搜索打开
O_APPEND每次写文件时都追加到文件的尾部
O_CLOEXEC将FD_CLOEXEC设置为文件描述符标志
O_CREAT若该文件不存在则创建
O_EXCL(指定了O_CREAT)若文件已存在则报错
O_NOFOLLOW若文件是一个符号链接则报错
O_SYNC对文件的修改将阻塞直到物理磁盘上同步为止
O_DIRECTORY若文件不是一个目录则失败
O_NONBLOCK以非阻塞的方式打开文件
O_NDELAY以非阻塞方式打开文件
O_TRUNC当文件存在并以可写方式打开则截断文件至0
errno定义的那些内容可以通过程序输出(这里感谢殷大佬的提示)

#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>

int main(void)
{
int i;
for(i = 0;i < 140;i++)
{
errno = i;
printf("%d error:%s\n",errno,strerror(errno));
}
return 0;
}


五、文件的读写

1、read函数

#include<unistd.h>
ssize_t read(int fd,void *buf,size_t count);
//从文件描述符fd所指向的文件中读取count个字节到buf中
//返回值表示世界读取字节数


2、write是从buf中读取count个字节到fd中

返回值相同

3、lseek函数

#include<unistd.h> #include<sys/types.h>
//和fseek类似


注意:

①fseek()不像lseek()会返回读写位置, 因此必须使用ftell()来取得目前读写的位置.

②lseek当调用成功时则返回目前的读写位置, 也就是距离文件开头多少个字节. 若有错误则返回-1, errno 会存放错误代码.

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>

void my_err(const char *err_string,int line)//错误处理
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}

int my_read(int fd)//读数据
{
int len;
int ret;
int i;
char read_buf[64];
//SEEK_END表示结束
//SEEK_SET表示开头
//SEEK_CUR表示当前位置
if(lseek(fd,0,SEEK_END)==-1)
my_err("lseek",__LINE__);
if((len=lseek(fd,0,SEEK_CUR))==-1)
my_err("lseek",__LINE__);
if((lseek(fd,0,SEEK_SET))==-1)
my_err("lseek",__LINE__);
if((ret=read(fd,read_buf,len))<0)
my_err("read",__LINE__);
printf("len:%d\n",len);
for(i=0;i<len;i++)
{
printf("%c",read_buf[i]);
}
putchar('\n');

return ret;
}
int main()
{
int fd;
char write_buf[32]="hello,world!";

//if((fd=creat("example_63.c",S_IRWXU))==-1)
if((fd=open("example_63.c",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU))==-1)
{
my_err("open",__LINE__);
}
else
printf("create file success\n");

//写数据   if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf))
my_err("write",__LINE__);
my_read(fd);

printf("/*-----------------*/\n");
if(lseek(fd,10,SEEK_END)==-1)
my_err("lseek",__LINE__);
if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf))
my_err("write",__LINE__);
my_read(fd);

close(fd);
return 0;
}


六、fcntl系统调用

1、#include<unistd.h>
#include<fcntl.h>
①int fcntl(int fd,int cmd)
②int fcntl(int fd,int cmd,long arg)
③int fcntl(int fd,int cmd,struct flock *lock)


#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>

void my_err(const char *err_string,int line)//错误处理函数
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}

int main()
{
int ret;
int access_mode;
int fd;   if((fd=open("example_64",O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))==-1)
my_err("open",__LINE__);
if((ret=fcntl(fd,F_SETFL,O_APPEND))<0)//设置文件打开方式
my_err("fcntl",__LINE__);

if((ret=fcntl(fd,F_GETFL,0))<0)//获取文件打开方式
my_err("fcntl",__LINE__);
access_mode=ret & O_ACCMODE;//O_ACCMODE为3,&可以获得ret后两位
if(access_mode==O_RDONLY)
printf("example_64 access_mode:read only");
else if(access_mode==O_WRONLY)
printf("example_64 access_mode:write only");
else if(access_mode==O_RDWR)
printf("example_64 access_mode:write+read");

if(ret&O_APPEND)
printf(" ,append");
printf("\n%d\n",O_APPEND);

printf("\n%d\n",O_NONBLOCK);

printf("\n%d\n",O_SYNC);
if(ret&O_NONBLOCK)
printf(",nonblock");
if(ret&O_SYNC)
printf(" ,sync");

putchar('\n');

return 0;
}


2、锁

共享锁言简意赅就是说大家可以读这个文件

互斥锁就是只能一个人去写这个文件,防止不同人打开,最后文件混乱

int fcntl(int fd,int cmd,struct flock *lock)

struct flock {
short l_type;/*锁的类型F_RDLCK, F_WRLCK, or F_UNLCK*/
off_t l_start;/*相对于l_whence的偏移值,字节为单位*/
short l_whence;/*从哪里开始:SEEK_SET, SEEK_CUR, or SEEK_END*/
off_t l_len;/*长度, 字节为单位; 0 意味着缩到文件结尾*/
pid_t l_pid;/*returned with F_GETLK*/
};


注意:

①cmd为中有一个F_GETTLK只是修改了结构体中锁的类型为F_UNLCK

②程序只是一个进程的时候可以设置写锁之后,设置读锁,但是多个进程的锁是不兼容的,所以下面的例子是单个进程

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<stdlib.h>

void my_err(const char *err_string,int line)
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}
//锁的设置或释放
int lock_set(int fd,struct flock *lock)
{
if(fcntl(fd,F_SETLK,lock)==0)
{
if(lock->l_type==F_RDLCK)
printf("set read lock,pid:%d\n",getpid());
//getpid()取得进程识别码
else if(lock->l_type==F_WRLCK)
printf("set write lock,pid:%d\n",getpid());
else if(lock->l_type==F_UNLCK)
printf("release lock,pid:%d\n",getpid());
}
else
{
perror("lock operation fail\n");
return -1;
}
}
//测试锁
int lock_test(int fd,struct flock *lock)
{
if(fcntl(fd,F_GETLK,lock)==0)
{
if(lock->l_type==F_UNLCK)
{
printf("lock can be set in fd\n");
return 0;
}
else
{
if(lock->l_type==F_RDLCK)
printf("can't set lock,read lock has been set by:%d\n",lock->l_pid);
else if(lock->l_type==F_WRLCK)
printf("can't set lock,write lock has been set by:%d\n",lock->l_pid);
}
return -2;
}
else
{
perror("get incompatible locks fail");
return -1;
}
}

int main()
{
int fd;
int ret;
struct flock lock;
char read_buf[32];
//打开文件
if((fd=open("example_65",O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))==-1)
my_err("open",__LINE__);
if(write(fd,"test lock",10)!=10)
my_err("write",__LINE__);
//初始化
memset(&lock,0,sizeof(struct flock));
lock.l_start=SEEK_SET;
lock.l_whence=0;
lock.l_len=0;

//设置读锁
lock.l_type=F_RDLCK;//就是检测可不可以设置读锁
if(lock_test(fd,&lock)==0)
{
lock.l_type=F_RDLCK;
lock_set(fd,&lock);
}
//读数据
lseek(fd,0,SEEK_SET);
if((ret=read(fd,read_buf,10))<0)
my_err("read",__LINE__);

read_buf[ret]='\0';
printf("%s\n",read_buf);

//任意键
getchar();
//设置写锁
lock.l_type=F_WRLCK;
if(lock_test(fd,&lock)==0)
{
lock.l_type=F_WRLCK;
lock_set(fd,&lock);
}
//释放锁
lock.l_type=F_UNLCK;
lock_set(fd,&lock);
close(fd);
return 0;
}


七、文件属性操作

1、获取文件属性int lstat(int fileds,char *file_name,struct stat*buf)

执行成功为0.失败为-1

struct stat  {
dev_t       st_dev;     /*文件所在设备的ID*/
ino_t       st_ino;     /* 节点号*/
mode_t      st_mode;    /* 文件的类型和存取的权限*/
nlink_t     st_nlink;   /* 链向此文件的连接数(硬连接)*/
uid_t       st_uid;     /* user's id*/
gid_t       st_gid;     /* group's id*/
dev_t       st_rdev;    /* 设备号,针对设备文件*/
off_t       st_size;    /* 文件大小,字节为单位*/
blksize_t   st_blksize; /* 系统块的大小*/
blkcnt_t    st_blocks;  /* 文件所占块数*/
time_t      st_atime;   /* 最近存取时间*/
time_t      st_mtime;   /* 最近修改时间*/
time_t      st_ctime;   /*最后状态修改时间*/
};


宏定义好的几个函数

参数含义
S_ISLNK(st_mode)是否是一个连接
S_ISREG(st_mode)是否是一个常规文件
S_ISDIR(st_mode)是否是一个目录
S_ISCHR(st_mode)是否是一个字符设备
S_ISBLK(st_mode)是否是一个块设备
S_ISFIFO(st_mode)是否 是一个FIFO文件
S_ISSOCK(st_mode)是否是一个SOCKET文件

2、设置文件属性

mode_t unmask(mode_t mask)屏蔽属性

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
umask(0);//不屏蔽
if(creat("example_681.test",S_IRWXU|S_IRWXG|S_IRWXO)<0)
{
perror("creat");
exit(1);
}
umask(S_IRWXO);//其他用户没有可读可写可执行
if(creat("example_682.test",S_IRWXU|S_IRWXG|S_IRWXO)<0)
{
perror("creat");
exit(1);
}
return 0;

}


八、目录的创建和删除、切换

1、目录的创建

#include<sys/stat.h>
#include<sys/typed.h>
int mkdir(const char *pathname,mode_t mode);


2、目录删除

#include<unistd.h>
int mkdir(const char *pathanme)


注意:只能删除空目录

3、获取当前目录

#include<unistd.h>
char *getcwd(char *buf,size_t size);
char *get_current_dir_name(void)
char *getwd(char *buf)


①get_current_dir_name获取当前工作目录

#define  _GNU_SOURCE
/*这是用来让用户配置编译环境的头文件。再看一下_GUN_SOURCE这个宏,这个宏可以让用户打开所有features.h文件的属性,而且其他头文件在获得这个宏定义之后才可以使用get——current_dir_name这个函数*/
#include<stdio.h>
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
char *path;
path = get_current_dir_name();
printf("%s>\n",path);
exit(0);

}

/*用gcc -E将预处理的代码导出来查看,如果宏定义的位置不正确。
导出的代码中不会包含get_current_dir_name()的函数原型,自然编译就认为它的返回值是默认的整数,从而导致一个警告。
把宏定义放在前面之后,gcc -E导出的代码中已经包含了正确的函数原型,警告就不会出现了。*/


②getcwd函数获取绝对路径

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(void)
{
char *path = NULL;
path = getcwd(NULL,0);
/*或者使用方法getcwd(path,256),256是给path分配的空间,path就储存了空间*/
puts(path);
free(path);
return 0;
}
/*可以采取令 buf 为 NULL并使 size 为零,来使 getcwd 调用 malloc 动态给 buf 分配,但是这种情况要特别注意使用后释放缓冲以防止内存泄漏。*/


4、切换工作目录

#include<unistd.h>
int chdir(const char *path);//path是目录参数
int fchdir(int fd);//fd是文件描述符号


例子是fchdir的使用

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
fd = open("../", O_RDONLY);
fchdir(fd);
printf("current working directory : %s \n", getcwd(NULL, 0));
close(fd);

}


九、获取目录信息

1、opendir

#include<sys/types.h>


#include<dirent.h>


DIR *opendir(const char *name)


失败返回NULL

2.readdir

#include<sys/types.h>


#include<dirent.h>


原型DIR *readdir(DIR*dir)


struct dirent{
long d_ino;//索引节点号
off_t d_off;//在文件中偏移量
unsigned short d_reclen;//文件名长
char d_name[NAME_MAX+1];
}


3.closedir

#include<sys/types.h>


#include<dirent.h>


原型DIR *closedir(DIR*dir)


#include<stdio.h>
#include<dirent.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int my_readir(const char *path)
{
DIR *dir;
struct dirent *ptr;

if((dir=opendir(path))==NULL)
{
perror("opendir");
return -1;
}
while((ptr=readdir(dir))!=NULL)//直到NULL才会停止读取
printf("File name:%s\n",ptr->d_name);
closedir(dir);

return 0;
}
int main(int argc,char *argv[])
{
if(argc<2)//判断参数
{
printf("listfile <target path>\n");
exit(1);
}
if(my_readir(argv[1])<0)
exit(1);

return 0;
}


注意:

这里所说的打开目录,只是获取了目录的信息,没有实际的进入你所打开的目录,你可以获取进入目录的名字,如果想切换目录,必须用chdir或fdir。用opendir打开,如果再想更深层次进入打开目录的目录是不可以的,opendir没有将你的目录切换。

比如你在linux目录下有一个ls目录,你打开了ls,发现ls目录下有个fun目录,你想进fun看看有什么,你会再次用opendir打开fun这个目录,但是实际上opendir会在linux目录下找fun,因为你的工作目录没有切换,当然linux下没有fun这个目录,就会报错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux文件操作