6.unlink
6.1 头文件包含
#include <unistd.h>
6.2 接口原型
int unlink(const char *pathname);
6.3 参数介绍
pathname 文件名
6.4 返回值
成功返回0,错误返回-1并且设置errno
6.5 用途
删除一个文件的目录项并减少它的链接数,如果想通过这个函数来删除一个文件,你必须拥有这个文件所属目录的读写权限
(1)如果是符号链接,则删除符号链接
(2)如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode
(3)如果文件硬链接为0时,但有进程已打开该文件,并持有文件描述符,则等进程关闭该文件时,kernel才真正去删除该文件
6.6 demo
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <fcntl.h>
#include <sys/types.h>
using namespace std;
int main(){
// 创建临时文件
int fd = open("file_tmp_unlink", O_CREAT | O_RDWR, 0664);
if(fd == -1){
perror("open");
exit(1);
}
// unlink减少硬链接数
if(unlink("file_tmp_unlink") == -1){
perror("unlink");
exit(1);
}
string str = "As long as you love me\n";
write(fd, str.data(), str.length());
if(lseek(fd, 0, SEEK_SET) == -1){
perror("lseek");
exit(1);
}
char buf[100];
read(fd, buf, sizeof(buf));
string res = buf;
write(1, res.data(), res.length());
close(fd);
return 0;
}
7.opendir
7.1 头文件包含
#include <sys/types.h>
#include <dirent.h>
7.2 接口原型
DIR *opendir(const char *name);
7.3 参数介绍
name 目录名字
7.4 返回值
成功打开目录时返回DIR结构体指针,该结构是一个内部结构,保存所打开的目录信息,作用类似于FILE结构。函数出错时返回NULL
7.5 用途
打开一个目录文件
8.readdir
8.1 头文件包含
#include <dirent.h>
8.2 接口原型
struct dirent *readdir(DIR *dirp);
8.3 参数介绍
传入的是一个目录指针,类型是DIR结构体。
8.4 返回值
返回的是一条记录项,类型是dirent结构体
dirent结构体原型为
struct dirent {
ino_t d_ino; //此目录进入点的inode
off_t d_off; // 目录文件开头至此目录进入点的位移
unsigned short d_reclen; // d_name 的长度,不包含
unsigned char d_type; // d_name 所指的文件类型
char d_name[256]; // 文件名
};
8.5 用途
读取目录
8.6 DEMO 获得指定目录中的普通文件个数
核心递归函数
int get_filesNum(const char *file_name){
// 获取dir目录指针
DIR * dir = opendir(file_name);
// 文件个数计数变量
int sum = 0;
// 目录打开失败
if(dir == NULL){
perror("open file error");
exit(1);
}else{
struct dirent * ptr = NULL;
// 遍历目录中的文件
while((ptr = readdir(dir)) != NULL){
if(!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, "..")){
continue;
}else if(ptr->d_type == DT_DIR){
// 递归读取目录
string dir_name = file_name;
dir_name += "/";
dir_name += ptr->d_name;
sum += get_filesNum(dir_name.data());
}else if(ptr->d_type == DT_REG){
++sum;
}
}
}
//关闭当前目录
closedir(dir);
//返回当前目录及子级目录的普通文件总数
return sum;
}
9.dup和dup2
9.1 头文件包含
#include <unistd.h>
9.2 接口原型
int dup(int oldfd);
int dup2(int oldfd, int newfd);
9.3 参数介绍
(1) dup
oldfd 文件描述符
(2) dup2
oldfd 原始文件描述符
newfd 复制到的文件描述符,若此文件描述符被占用,将关闭该文件描述符所占用的文件,再把oldfd的文件描述符复制到newfd
9.4 返回值
(1) dup
返回的是文杰描述符表中没有被占用的最小的文件描述符
(2) dup2
返回复制的文件描述符
9.5 用途
复制文件描述符号,可以使多个文件描述符(fd)指向同一个文件指针,操作同一个文件
9.6 DEMO
Description
创建一个文件, 描述符为fd,首先用dup把新的文件描述符fd2指向 fd指向的文件,分别向fd和fd2指向的文件写入信息。用dup2 把fd指向文件描述符为1的文件指针,再用dup2把fd2指向fd指向的文件,第一次关闭fd所指向的文件,第二次dup2再关闭fd2指向的文件,第二次dup2后,创建出的新的文件已经没有文件描述符所占用。最后向fd,fd2指向的文件输出信息,因为文件描述符1是标准输出,指向控制台终端,所以最后的信息将输出到控制台。
Code
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
void write_something(const int & fd, const int & fd2){
// prepare two strings for writing
string str = "As long as you love me.....\n";
string str2 = "I like to make myself believe that I can make it!\n";
// write str to the pointer file of fd
write(fd, str.data(), str.length());
// write str2 to the pointer file of fd2
write(fd2, str2.data(), str2.length());
}
int main(){
int fd = open("dup_test.txt", O_CREAT | O_APPEND | O_RDWR, 0664);
// dup fd->fd2
int fd2 = dup(fd);
// show nums of fd and fd2
cout << "fd: " << fd << endl;
cout << "fd2: " << fd2 << endl;
// write something
write_something(fd, fd2);
// dup2 1->fd, fd point the file of 1
fd = dup2(1, fd);
// dup2 1->fd2, fd2 point the file of fd
fd2 = dup2(fd, fd2);
// show nums of fd and fd2
cout << "fd: " << fd << endl;
cout << "fd2: " << fd2 << endl;
// write something
write_something(fd, fd2);
close(fd);
close(fd2);
return 0;
}
10.fcntl函数
10.1 头文件包含
#include <unistd.h>
#include <fcntl.h>
10.2 接口原型
(1) int fcntl(int fd, int cmd);
(2) int fcntl(int fd, int cmd, long arg);
(3) int fcntl(int fd, int cmd, struct flock * lock);
10.3 参数介绍
fd 文件描述符
cmd 操作标志,用途中将详细介绍
arg 文件状态标记
10.4 返回值
返回值依赖于传入的参数的使用操作,失败时返回-1
关于设置的操作成功时统一返回0
10.5 用途
根据文件描述符来操作文件的状态
ps:à为取值符
(1)复制一个现有的描述符 cmd à F_DUPFD, 使用原型(1)
(2)获得/设置文件描述符标记 cmd à{F_GETFD, F_SETFD}, 使用原型(1)
(3)获得/设置文件状态标记
使用原型(2)
cmdà{F_GETFD, F_SETFD}
F_GETFLà{O_RDONLY, O_WRONLY, 0_RDWR, O_EXEC, O_SEARCH, O_APPEND, O_NOBLOCK}
F_SETFLà{O_APPEND, O_NONBLOCK}
(4)获得/设置异步I/O所有权 cmdà{F_GETOWN, F_SETOWN},使用原型(1)
(5)获得/设置记录锁 cmdà{F_GETLK, F_SETLK, F_SETLKW}
10.6 DEMO
开始时以只写方式打开文件,向文件写入数据,新的数据将覆盖原来的数据;使用fcntl将文件描述符fd对应的文件标志状态增加追加写,再次向fd指向的文件写入新的数据,数据将在旧的数据末尾追加写入
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
int main(){
int fd;
int flag;
// test strings
string str1 = "I like to make myself believe that I can make it!\n";
string str2 = "Hello world! Hello my friends!\n";
//open the file that only can write
fd = open("test.txt", O_WRONLY);
if(fd == -1){
perror("open");
exit(1);
}
// input new message for the file and cover the old message
if(write(fd, str1.data(), str1.length()) == -1){
perror("write");
exit(1);
}
// use F_GETFL to get the flag of the file status
flag = fcntl(fd, F_GETFL, 0);
if(flag == -1){
perror("fcntl");
exit(1);
}
// set file status flag of O_APPEND
flag |= O_APPEND;
// change the file status that set it for append write
if(fcntl(fd, F_SETFL, flag) == -1){
perror("fcntl -- append write");
exit(1);
}
// input the message again, the new message will show append the old message
if(write(fd, str2.data(), str2.length()) == -1){
perror("write again");
exit(1);
}
close(fd);
return 0;
}
Comments