本文是在牛客学习高新求职项目:Linux高并发服务器时所写
接上文:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/131563318
目录
一、stat结构体
stat 结构体 struct stat { dev_t st_dev; // 文件的设备编号
ino_t st_ino; // 节点
mode_t st_mode; // 文件的类型和存取的权限
nlink_t st_nlink; // 连到该文件的硬连接数目
uid_t st_uid; // 用户ID
gid_t st_gid; // 组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; // 最后一次改变时间(指属性)
二、st_mode变量
三、文件属性操作函数
◼int access(const char *pathname, int mode);
◼ int chmod(const char *filename, int mode);
◼ int chown(const char *path, uid_t owner, gid_t group);
◼ int truncate(const char *path, off_t length);
1.access函数
#include <unistd.h>
int access(const char *pathname, int mode);
作用:判断文件是否有某个权限,是否存在
参数:
pathname:判断文件的路径
mdoe:
R_OK:判断文件是否有读权限
W_OK:判断文件是否有写权限
X_OK:判断是否有执行权限
F_OK:判断文件是否存在
返回值:成功返回0,失败返回-1
#include <unistd.h>
#include <stdio.h>
int main()
{
int ret = access("a.txt",F_OK);
if(ret == -1){
perror("access");
return -1;
}
printf("文件存在!!\n");
return 0;
}
2.chmod函数
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
修改文件的权限
参数:
pathname:需要修改的文件的路径
mode:需要修改的权限值,八进制的数
返回值:成功返回0,失败返回-1
int fchmod(int fd, mode_t mode);
#include <sys/stat.h>
#include<stdio.h>
int main()
{
int ret = chmod("a.txt",0775);
if(ret == -1){
perror("chmod");
return -1;
}
return 0;
}
3. truncate函数
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
作用:缩减或者扩展文件的尺寸至指定的大小
参数:
path:需要修改的文件路径
length:需要最终文件变成的大小
返回值:成功返回0,失败返回-1
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main(){
int ret = truncate("b.txt",20);
if(ret == -1){
perror("truncate");
return -1;
}
return 0;
}
四、目录操作函数
1.int rename(const char *oldpath, const char *newpath);
2.int chdir(const char *path);
3.char *getcwd(char *buf, size_t size);
4.int mkdir(const char *pathname, mode_t mode);
5.int rmdir(const char *pathname);
1. chdir函数
#include <unistd.h>
int chdir(const char *path);
作用:修改进程的工作目录
比如在/home/china下启动了一个可执行程序a.out,进程的工作目录就是/home/china
参数:
需要修改的工作目录。
#include <unistd.h>
char *getcwd(char *buf, size_t size);
作用:获取当前工作目录
参数:
buf:存储的路径,指向的是当前的数组。
size:指定数组的大小。
返回值:
返回的指向的一块内存,这个数据就是第一个参数
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
//获取当前的工作目录
char buf[128];
getcwd(buf,sizeof(buf));
printf("当前的工目录:%s\n",buf);
//修改工作目录
int ret = chdir("/home/china/Linux/lesson13");
if(ret ==-1){
printf("chdir");
return -1;
}
int fd = open("chdir.txt",O_CREAT|O_RDWR,0664);
if(fd == -1){
perror("open");
return -1;
}
close(fd);
char buf1[128];
getcwd(buf1,sizeof(buf1));
printf("当前的工目录:%s\n",buf1);
return 0;
}
2.rename函数
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
作用:重命名目录
#include <stdio.h>
int main()
{
int ret = rename("aaa","bbb");
if(ret == -1){
perror("rename");
}
return 0;
}
3. mkdir函数
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
作用:创建一个目录
参数:
pathname:创建的目录的名称或者路径
mode:权限,八进制的整数
int rmdir(const char *pathname);
作用:删除目录,只能删除空目录
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
int main()
{
int ret = mkdir("aaa",0777);
if(ret == -1){
perror("mkdir");
}
return 0;
}
五、目录遍历函数
1.DIR *opendir(const char *name);
2.truct dirent *readdir(DIR *dirp);
3.int closedir(DIR *dirp);
1.opendir
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
参数:
name:需要打开的目录的名称
返回值:DIR * 类型,理解为目录流
返回值:错误返回NULL
//读取目录中的数据
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
参数:dirp是opendir返回的结果
返回值:
struct dirent:代表读取到的文件信息
读取到末尾或者失败了,返回NULL
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
参数:关闭目录
//读取某个目录下所有普通文件的个数
#define _DEFAULT_SOURCE
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int getFileNum(char *path);
int main(int argc,char * argv[])
{
if(argc < 2){
printf("%s path\n",argv[0]);
return -1;
}
int num=getFileNum(argv[1]);
printf("普通文件的个数:%d\n",num);
return 0;
}
//用于获取普通文件下所有普通文件的个数
int getFileNum(char *path){
// 1.打开目录
DIR *dir = opendir(path);
if( dir == NULL){
perror("opendir");
exit(0);
}
struct dirent * ptr ;
int total=0;
while((ptr = readdir(dir))!=NULL) {
//获取名称
char * dname = ptr->d_name;
if(strcmp(dname,".")==0||strcmp(dname,"..")==0){
continue;
}
//p判断是否是普通文件还是目录,是目录的画需要调用函数递归计算;
if(ptr->d_type== DT_DIR){
//目录,需要继续读取这个目录
char newpath[256];
sprintf(newpath,"%s/%s",path,dname);
total+=getFileNum(newpath);
}
if(ptr->d_type ==DT_REG){
//普通文件
total++;
}
}
closedir(dir);
return total;
}
六、dup、dup2函数
1.int dup(int oldfd); 复制文件描述符
2.int dup2(int oldfd, int newfd); 重定向文件描述符
1.dup函数
#include <unistd.h>int dup(int oldfd);
作用:复制一个新的文件描述符
fd1 = 3, int fd1 = dup(fd),
fd指向的是a.txt,fd1也是指向a.txt
从空闲的文件描述符表中找一个最小的,作为新的拷贝的文件描述符*/
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(){
int fd = open("a.txt",O_RDWR | O_CREAT,0664);
int fd1 = dup(fd);
if(fd1 == -1){
perror("dup");
return -1;
}
printf("fd:%d, fd1: %d",fd,fd1);
close(fd);
char *str = "hello world";
int ret = write(fd1,str,strlen(str));
if(ret == -1){
perror("write");
return -1;
}
close(fd1);
return 0;
}
2.dup2函数
#include <unistd.h>
int dup2(int oldfd, int newfd);
作用:重定向文件描述符
oldfd 指向 a.txt,newfd 指向b.txt
调用函数成功后:newfd和b.txt做close,newfd指向了a.txt
oldfd 必须是一个有效的文件描述符
oldfd和newfd值相同,相当于什么都没有做
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
int fd = open("1.txt",O_RDWR | O_CREAT,0664);
if(fd == -1){
perror("open");
return -1;
}
int fd1 = open("2.txt",O_RDWR | O_CREAT,0664);
if(fd1 == -1){
perror("open");
return -1;
}
printf("fd:%d, fd1:%d\n",fd,fd1);
int fd2 = dup2(fd,fd1);
if(fd2 == -1){
perror("dup2");
return -1;
}
//通过fd1去写数据,实际操作的是1.txt,而不是2.txt
char *str = "hello";
int len = write(fd1,str,strlen(str));
if(len ==-1){
perror("write");
return -1;
}
printf("fd:%d, fd1:%d fd2:%d\n",fd,fd1,fd2);
close(fd);
close(fd1);
return 0;
}
七、fcntl函数
#include <unistd.h>
#include <fcntl.h>int fcntl(int fd, int cmd,..... );
参数:
fd:表示需要操作的文件描述符
cmd:表示对文件描述符进行如何操作
F_DUPFD:复制文件描述符,复制的第一个参数是fd,得到一个新的
int ret = fcntl(fd,F_DUPFD);F_GETFL:获取指定文件描述符文件状态flag
获取的flag和我们通过open函数传递的flag是一个东西F_SETFL:设置文件描述符文件状态falg
必选项:O_RDONLY,O_WRONLY,O_RDWR 不会被修改
可选项:O_APPEND,O_NONBLOCK
O_APPEND:表示追加数据
O_NONBLOCK:设置成非阻塞
阻塞和非阻塞:描述的函数调用的行为。add()
#include <unistd.h>
#include <fcntl.h>
#include<stdio.h>
#include<string.h>
int main(){
//1.复制文件描述符
//int fd = open("1.txt",O_RDONLY);
//int ret =fcntl(fd,F_DUPFD);
//2.修改或者获取文件的flag
int fd = open("1.txt",O_RDWR|O_CREAT,0664);
if(fd == -1){
perror("open");
return -1;
}
//获取文件描述符状态flag
int flag = fcntl(fd,F_GETFL);
flag|=O_APPEND;
//修改文件描述符的flag,给flag加入O_APPEND这个标记
int ret = fcntl(fd,F_SETFL,flag);
if(ret == -1){
perror("fcntl");
return -1;
}
char *str="hjhvjnnn";
write(fd,str,strlen(str));
close(fd);
}