鸿蒙内核源码分析(文件句柄篇) | 你为什么叫句柄

句柄 | handle

int open(const char* pathname,int flags);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);

只要写过应用程序代码操作过文件不会陌生这几个函数,文件操作的几个关键步骤嘛,跟把大象装冰箱分几步一样.先得把冰箱门打开,再把大象放进去,再关上冰箱门.其中最重要的一个参数就是fd,应用程序所有对文件的操作都基于它.fd可称为文件描述符,或者叫文件句柄(handle),个人更愿意称后者. 因为更形象,handle英文有手柄的意思,跟开门一样,握住手柄才能开门,手柄是进门关门的抓手.映射到文件系统,fd是应用层出入内核层的抓手.句柄是一个数字编号, open | creat去申请这个编号,内核会创建文件相关的一系列对象,返回编号,后续通过编号就可以操作这些对象.原理就是这么的简单,本篇将从fd入手,跟踪文件操作的整个过程.

请记住,鸿蒙内核中,在不同的层面会有两种文件句柄:

  • 系统文件句柄(sysfd),由内核统一管理,和进程文件句柄形成映射关系,一个sysfd可以被多个profd映射,也就是说打开一个文件只会占用一个sysfd,但可以占用多个profd,即一个文件被多个进程打开.
  • 进程文件句柄(profd),由进程管理的叫进程文件句柄,内核对不同进程中的fd进行隔离,即进程只能访问本进程的fd.举例说明之间的关系:
    文件            sysfd     profd
    吃个桃桃.mp4        10    13(A进程)
    吃个桃桃.mp4        10    3(B进程)
    容嬷嬷被冤枉.txt    12    3(A进程)
    容嬷嬷被冤枉.txt    12    3(C进程)

进程文件句柄

在鸿蒙一个进程默认最多可以有256fd,即最多可打开256个文件.文件也是资源的一种,系列篇多次说过进程是管理资源的,所以在进程控制块中能看到文件的影子files_structfiles_struct可理解为进程的文件管理器,里面只放和本进程相关的文件,线程则共享这些文件.另外子进程也会拷贝一份父进程的files_struct到自己的files_struct上,在父子进程篇中也讲过fork的本质就是拷贝资源,其中就包括了文件内容.

//进程控制块
typedef struct ProcessCB {
    //..
    #ifdef LOSCFG_FS_VFS
        struct files_struct *files;        /**< Files held by the process */ //进程所持有的所有文件,注者称之为进程的文件管理器
    #endif	//每个进程都有属于自己的文件管理器,记录对文件的操作. 注意:一个文件可以被多个进程操作
} LosProcessCB;
struct files_struct {//进程文件表结构体
    int count;				//持有的文件数量
    struct fd_table_s *fdt; //持有的文件表
    unsigned int file_lock;	//文件互斥锁
    unsigned int next_fd;	//下一个fd
#ifdef VFS_USING_WORKDIR
    spinlock_t workdir_lock;	//工作区目录自旋锁
    char workdir[PATH_MAX];		//工作区路径,最大 256个字符
#endif
};

fd_table_sfiles_struct的成员,负责记录所有进程文件句柄的信息,个人觉得鸿蒙这块的实现有点乱,没有封装好.

struct fd_table_s {//进程fd表结构体
    unsigned int max_fds;//进程的文件描述符最多有256个
    struct file_table_s *ft_fds; /* process fd array associate with system fd *///系统分配给进程的FD数组 ,fd 默认是 -1
    fd_set *proc_fds;	//进程fd管理位,用bitmap管理FD使用情况,默认打开了 0,1,2	       (stdin,stdout,stderr)
    fd_set *cloexec_fds;
    sem_t ft_sem; /* manage access to the file table */ //管理对文件表的访问的信号量
};

file_table_s 记录进程fd和系统fd之间的绑定或者说映射关系

struct file_table_s {//进程fd <--> 系统fd绑定
    intptr_t sysFd; /* system fd associate with the tg_filelist index */
};

fd_set实现了进程fd按位图管理,系列操作为 FD_SET,FD_ISSET,FD_CLR,FD_ZERO
除以8是因为 char类型占8bit位.请尝试去理解下按位操作的具体实现.

typedef struct fd_set
{
  unsigned char fd_bits [(FD_SETSIZE+7)/8];
} fd_set;
#define FD_SET(n, p)  FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] = (u8_t)((p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |  (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))))
#define FD_CLR(n, p)  FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] = (u8_t)((p)->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值