前述
今天总结一下文件操作,主要包括两部分,文件描述符的控制和my_ls的实现。
正文
1.对文件描述符进行控制操作以改变一打开文件的属性,fcntl函数原型如下
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg );
int fcntl(int fd, int cmd, struct flock *flock);
struct flock{
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
}
这里主要谈涉及到文件记录锁的第三种形式。
文件记录锁
文件记录锁是当多个进程同时对文件进行操作时,通过锁限制进程对文件的操作,比如读锁(F_RDLCK)允许一块文件内容多个进程同时读,而写锁(F_WRLCK)对一块文件内容只允许一个进程写。而两种所互不兼容,即对于一个字节只能存在一种类型的锁
此时cmd参数有三种形式:F_SETLK,F_SETLKW,F_GETLK.
1.F_SETLK 设置锁,我理解为按flock指向的结构体中的信息对fd进行设置
2.F_SETLKW 与上一条相似,但当希望设置的锁由于已经存在了其他锁而被阻止时,会等待直到那锁被释放。
3.F_GETLK 检测能否设置锁,如果可以将lock的l_type设置为F_UNLCK否则返回存在冲突的一种锁的结构。
当设置锁时,流程如下(以设置写锁为例)
struct flock lock;
memset(&lock, 0, sizeof(struct flock)); //初始化结构体
lock.l_type = F_WRLCK;//设置要写的属性包括whence等
if((fcntl(fd, F_GETLK, lock)) == 0) //测试
{
if(lock -> l_type == F_UNLCK)
{
printf("lock can be set in fd\n");
}
else{
if(lock -> l_type == F_RDLCK)
printf("can't set lock ");
else if(lock -> l_type == F_WRLCK)
printf("can't set lock ");
}
}
else {
perror("get incompatible locks fail");
return -1
}
lock.l_type = F_WRLCK;
if((fcntl(fd, F_SETLK, lock)) == 0)
{
if(lock -> l_type == F_RDLCK)
printf("set read lock\n");
else if(lock -> l_type == F_WRLCK)
printf("set write lock \n");
else if(lock -> l_type == F_UNLCK)
printf("release lock\n",);
}
else {
perror("lock operation fail\n");
return -1;
}
return 0;
2.my_ls的实现
感觉并不是很难,但确实有一些地方做的不好。
下面以-Rl参数作为代表说一下
我的函数调用传递的形参为文件路径,用opendir函数打开要查看的目录,返回的dir指针再传递给readdir函数用来找到ptr指针,从而得到文件名,再有文件名通过stat函数读取文件信息存放在结构体数组file中,因为结构体stat中没有成员变量保存文件名,于是我又定义了一个指针数组用来记录文件名,也方便对文件名排序。
int my_readir_rl(const char *path)
{
DIR *dir;
char dir_name[100][50];
struct dirent *ptr;
int i = 0,tem,key =0;;
/*用路径打开目录*/
if((dir = opendir(path)) == NULL)
{
perror("opendir");
return -1;
}
/*将进程的当前工作目录转换为要查看的目录*/
chdir(path);
printf("----------------- %s------------------\n",path);
//通过ptr获取文件名
while((ptr = readdir(dir)) != NULL&&i < 99)
{
//不读取隐藏文件及目录
if((ptr -> d_name)[0] == '.')
continue;
//获取文件信息存入结构体数组
stat(ptr -> d_name, &file[i]);
//记录文件名
name[i] = ptr -> d_name;
//判断当前文件是否为一个目录
if((tem = (file[i].st_mode /512)) == 32)
{
//获取当前目录绝对路径
getcwd(dir_name[key],512);
//将子目录的目录名补全为绝对路径记录在dirname数组中
strcat(dir_name[key],"/");
strcat(dir_name[key], name[i]);
key++;
}
i++;
}
//按照文件名进行排序
bubble_sort(i);
//将文件权限由mode_t转换为rwx的字符串
change_mode_t(i);
//打印信息
print(i);
//将之前记录的子目录绝对路径再次调用函数读取显示信息
for(tem =0; tem < key; tem++)
{
my_readir_rl(dir_name[tem]);
}
return 0;
}
没有采用链表的数据结构,导致并不能显示太多的文件信息。