更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
vfs_procfd.c 文件参考

浏览源代码.

函数

void FileTableLock (struct fd_table_s *fdt)
 对进程文件表操作上锁 更多...
 
void FileTableUnLock (struct fd_table_s *fdt)
 对进程文件表操作解锁 更多...
 
static int AssignProcessFd (const struct fd_table_s *fdt, int minFd)
 分配进程描述符 更多...
 
struct fd_table_sGetFdTable (void)
 获取进程文件描述符表 更多...
 
static bool IsValidProcessFd (struct fd_table_s *fdt, int procFd)
 
void AssociateSystemFd (int procFd, int sysFd)
 参数进程FD和参数系统FD进行绑定(关联) 更多...
 
int CheckProcessFd (int procFd)
 
int GetAssociatedSystemFd (int procFd)
 获取绑定的系统描述符 更多...
 
int AllocSpecifiedProcessFd (int procFd)
 
void FreeProcessFd (int procFd)
 释放进程文件描述符 更多...
 
int DisassociateProcessFd (int procFd)
 解绑系统文件描述符,返回系统文件描述符 更多...
 
int AllocProcessFd (void)
 分配文件描述符 更多...
 
int AllocLowestProcessFd (int minFd)
 分配文件描述符,从3号开始 更多...
 
int AllocAndAssocProcessFd (int sysFd, int minFd)
 分配和绑定进程描述符 更多...
 
int AllocAndAssocSystemFd (int procFd, int minFd)
 分配和绑定系统描述符 更多...
 
static void FdRefer (int sysFd)
 进程FD引用数改变 更多...
 
static void FdClose (int sysFd, unsigned int targetPid)
 关闭FD 更多...
 
static struct fd_table_sGetProcessFTable (unsigned int pid, sem_t *semId)
 获取参数进程FD表 更多...
 
int CopyFdToProc (int fd, unsigned int targetPid)
 拷贝一个进程FD给指定的进程,使两个进程的FD都指向同一个系统FD 更多...
 
int CloseProcFd (int procFd, unsigned int targetPid)
 关闭进程FD 更多...
 

函数说明

◆ AllocAndAssocProcessFd()

int AllocAndAssocProcessFd ( int  sysFd,
int  minFd 
)

分配和绑定进程描述符

在文件 vfs_procfd.c261 行定义.

262{
263 struct fd_table_s *fdt = GetFdTable();
264
265 if (fdt == NULL) {
266 return VFS_ERROR;
267 }
268
269 /* minFd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */
270 if (minFd < MIN_START_FD) {
271 minFd = MIN_START_FD;
272 }
273
274 FileTableLock(fdt);
275
276 int procFd = AssignProcessFd(fdt, minFd);
277 if (procFd == VFS_ERROR) {
278 FileTableUnLock(fdt);
279 return VFS_ERROR;
280 }
281
282 /* occupy the fd set */
283 FD_SET(procFd, fdt->proc_fds);
284 fdt->ft_fds[procFd].sysFd = sysFd;
285 FileTableUnLock(fdt);
286
287 return procFd;
288}
进程fd表结构体
Definition: fd_table.h:84
struct file_table_s * ft_fds
Definition: fd_table.h:86
fd_set * proc_fds
进程fd管理位,用bitmap管理FD使用情况,默认打开了 0,1,2 (stdin,stdout,stderr)
Definition: fd_table.h:87
intptr_t sysFd
Definition: fd_table.h:81
struct fd_table_s * GetFdTable(void)
获取进程文件描述符表
Definition: vfs_procfd.c:77
void FileTableLock(struct fd_table_s *fdt)
对进程文件表操作上锁
Definition: vfs_procfd.c:40
static int AssignProcessFd(const struct fd_table_s *fdt, int minFd)
分配进程描述符
Definition: vfs_procfd.c:60
void FileTableUnLock(struct fd_table_s *fdt)
对进程文件表操作解锁
Definition: vfs_procfd.c:52
函数调用图:
这是这个函数的调用关系图:

◆ AllocAndAssocSystemFd()

int AllocAndAssocSystemFd ( int  procFd,
int  minFd 
)

分配和绑定系统描述符

在文件 vfs_procfd.c290 行定义.

291{
292 struct fd_table_s *fdt = GetFdTable();//获取当前进程文件表
293
294 if (!IsValidProcessFd(fdt, procFd)) {
295 return VFS_ERROR;
296 }
297
298 int sysFd = alloc_fd(minFd);//1.分配一个系统描述符,从全局文件描述符 tg_filelist 表中分配
299 if (sysFd < 0) {
300 return VFS_ERROR;
301 }
302
303 FileTableLock(fdt);
304 fdt->ft_fds[procFd].sysFd = sysFd;//2.将进程描述符和系统描述符绑定
305 FileTableUnLock(fdt);
306
307 return sysFd;
308}
int alloc_fd(int minfd)
分配一个系统fd,从全局tg_filelist中拿sysFd
static bool IsValidProcessFd(struct fd_table_s *fdt, int procFd)
Definition: vfs_procfd.c:94
函数调用图:

◆ AllocLowestProcessFd()

int AllocLowestProcessFd ( int  minFd)

分配文件描述符,从3号开始

在文件 vfs_procfd.c233 行定义.

234{
235 struct fd_table_s *fdt = GetFdTable();
236
237 if (fdt == NULL) {
238 return VFS_ERROR;
239 }
240 //minFd 应该是一个正数,并且 0,1,2 已经分配给 stdin,stdout,stderr
241 /* minFd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */
242 if (minFd < MIN_START_FD) {
243 minFd = MIN_START_FD;
244 }
245
246 FileTableLock(fdt);
247
248 int procFd = AssignProcessFd(fdt, minFd);
249 if (procFd == VFS_ERROR) {
250 FileTableUnLock(fdt);
251 return VFS_ERROR;
252 }
253
254 /* occupy the fd set */
255 FD_SET(procFd, fdt->proc_fds);//占用该进程文件描述符
256 FileTableUnLock(fdt);
257
258 return procFd;
259}
函数调用图:
这是这个函数的调用关系图:

◆ AllocProcessFd()

int AllocProcessFd ( void  )

分配文件描述符

在文件 vfs_procfd.c228 行定义.

229{
230 return AllocLowestProcessFd(MIN_START_FD);
231}
int AllocLowestProcessFd(int minFd)
分配文件描述符,从3号开始
Definition: vfs_procfd.c:233
函数调用图:
这是这个函数的调用关系图:

◆ AllocSpecifiedProcessFd()

int AllocSpecifiedProcessFd ( int  procFd)

在文件 vfs_procfd.c162 行定义.

163{
164 struct fd_table_s *fdt = GetFdTable();//获取进程FD表
165
166 if (!IsValidProcessFd(fdt, procFd)) {
167 return -EBADF;
168 }
169
170 FileTableLock(fdt);
171 if (fdt->ft_fds[procFd].sysFd >= 0) {//第一种情况
172 /* Disassociate procFd */
173 fdt->ft_fds[procFd].sysFd = -1;//解除关联
174 FileTableUnLock(fdt);
175 return OK;
176 }
177
178 if (FD_ISSET(procFd, fdt->proc_fds)) {//还在使用中
179 /* procFd in race condition */
180 FileTableUnLock(fdt);
181 return -EBUSY;
182 } else {//未分配情况
183 /* Unused procFd */
184 FD_SET(procFd, fdt->proc_fds);//立即占用
185 }
186
187 FileTableUnLock(fdt);
188 return OK;
189}
函数调用图:
这是这个函数的调用关系图:

◆ AssignProcessFd()

static int AssignProcessFd ( const struct fd_table_s fdt,
int  minFd 
)
static

分配进程描述符

在文件 vfs_procfd.c60 行定义.

61{
62 if (minFd >= fdt->max_fds) {
63 set_errno(EINVAL);
64 return VFS_ERROR;
65 }
66 //从表中搜索未使用的 fd
67 /* search unused fd from table */
68 for (int i = minFd; i < fdt->max_fds; i++) {
69 if (!FD_ISSET(i, fdt->proc_fds)) {
70 return i;
71 }
72 }
73 set_errno(EMFILE);
74 return VFS_ERROR;
75}
unsigned int max_fds
进程的文件描述符最多有256个
Definition: fd_table.h:85
这是这个函数的调用关系图:

◆ AssociateSystemFd()

void AssociateSystemFd ( int  procFd,
int  sysFd 
)

参数进程FD和参数系统FD进行绑定(关联)

在文件 vfs_procfd.c105 行定义.

106{
107 struct fd_table_s *fdt = GetFdTable();//获取当前进程FD表
108
109 if (!IsValidProcessFd(fdt, procFd)) {
110 return;
111 }
112
113 if (sysFd < 0) {
114 return;
115 }
116
117 FileTableLock(fdt);
118 fdt->ft_fds[procFd].sysFd = sysFd;//绑定
119 FileTableUnLock(fdt);
120}
函数调用图:
这是这个函数的调用关系图:

◆ CheckProcessFd()

int CheckProcessFd ( int  procFd)

在文件 vfs_procfd.c122 行定义.

123{
124 struct fd_table_s *fdt = GetFdTable();
125
126 if (!IsValidProcessFd(fdt, procFd)) {
127 return VFS_ERROR;
128 }
129
130 return OK;
131}
函数调用图:
这是这个函数的调用关系图:

◆ CloseProcFd()

int CloseProcFd ( int  procFd,
unsigned int  targetPid 
)

关闭进程FD

在文件 vfs_procfd.c431 行定义.

432{
433#if !defined(LOSCFG_NET_LWIP_SACK) && !defined(LOSCFG_COMPAT_POSIX) && !defined(LOSCFG_FS_VFS)
434 return -ENOSYS;
435#else
436 int sysFd;
437 struct fd_table_s *fdt = NULL;
438 sem_t semId;
439
440 if (OS_PID_CHECK_INVALID(targetPid)) {
441 return -EINVAL;
442 }
443
444 fdt = GetProcessFTable(targetPid, &semId);//获取进程文件描述表
445 if (fdt == NULL || fdt->ft_fds == NULL) {
446 return -EPERM;
447 }
448
449 /* Take the semaphore (perhaps waiting) */
450 if (sem_wait(&semId) != 0) {
451 /* Target process changed */
452 return -ESRCH;
453 }
454
455 if (!IsValidProcessFd(fdt, procFd)) {
456 if (sem_post(&semId) == -1) {
457 PRINTK("sem_post error, errno %d \n", get_errno());
458 }
459 return -EPERM;
460 }
461
462 sysFd = fdt->ft_fds[procFd].sysFd;//获取参数进程描述符绑定的系统文件描述符
463 if (sysFd < 0) {
464 if (sem_post(&semId) == -1) {
465 PRINTK("sem_post error, errno %d \n", get_errno());
466 }
467 return -EPERM;
468 }
469
470 /* clean the fd set */
471 FD_CLR(procFd, fdt->proc_fds);//进程FD重置
472 FD_CLR(procFd, fdt->cloexec_fds);
473 fdt->ft_fds[procFd].sysFd = -1;//解绑
474 if (sem_post(&semId) == -1) {
475 PRINTK("sem_post error, errno %d \n", get_errno());
476 }
477 FdClose(sysFd, targetPid);//注意这个操作只是让对应的引用数量减少
478
479 return 0;
480#endif
481}
int sem_post(sem_t *sem)
增加信号量计数
Definition: semaphore.c:139
int sem_wait(sem_t *sem)
获取信号量
Definition: semaphore.c:77
fd_set * cloexec_fds
Definition: fd_table.h:88
static struct fd_table_s * GetProcessFTable(unsigned int pid, sem_t *semId)
获取参数进程FD表
Definition: vfs_procfd.c:354
static void FdClose(int sysFd, unsigned int targetPid)
关闭FD
Definition: vfs_procfd.c:327
函数调用图:
这是这个函数的调用关系图:

◆ CopyFdToProc()

int CopyFdToProc ( int  fd,
unsigned int  targetPid 
)

拷贝一个进程FD给指定的进程,使两个进程的FD都指向同一个系统FD

在文件 vfs_procfd.c378 行定义.

379{
380#if !defined(LOSCFG_NET_LWIP_SACK) && !defined(LOSCFG_COMPAT_POSIX) && !defined(LOSCFG_FS_VFS)
381 return -ENOSYS;
382#else
383 int sysFd;
384 struct fd_table_s *fdt = NULL;
385 int procFd;
386 sem_t semId;
387
388 if (OS_PID_CHECK_INVALID(targetPid)) {
389 return -EINVAL;
390 }
391
392 sysFd = GetAssociatedSystemFd(fd);//找到当前进程FD绑定的系统FD
393 if (sysFd < 0) {
394 return -EBADF;
395 }
396
397 FdRefer(sysFd);//引用数要增加了.
398 fdt = GetProcessFTable(targetPid, &semId);//获取目标进程的FD表
399 if (fdt == NULL || fdt->ft_fds == NULL) {
400 FdClose(sysFd, targetPid);
401 return -EPERM;
402 }
403
404 /* Take the semaphore (perhaps waiting) */
405 if (sem_wait(&semId) != 0) {
406 /* Target process changed */
407 FdClose(sysFd, targetPid);
408 return -ESRCH;
409 }
410
411 procFd = AssignProcessFd(fdt, 3);//从目标进程FD表中分配一个FD出来,注意这个FD编号不一定和当前进程的编号相同,但他们都将绑定在同一个系统FD上
412 if (procFd < 0) {
413 if (sem_post(&semId) == -1) {
414 PRINT_ERR("sem_post error, errno %d \n", get_errno());
415 }
416 FdClose(sysFd, targetPid);
417 return -EPERM;
418 }
419
420 /* occupy the fd set */
421 FD_SET(procFd, fdt->proc_fds);//申请到了等啥呀,赶紧占用这个FD
422 fdt->ft_fds[procFd].sysFd = sysFd;//绑定,这句话代表的意思是有两个进程的FD都帮到同一个系统FD上
423 if (sem_post(&semId) == -1) {
424 PRINTK("sem_post error, errno %d \n", get_errno());
425 }
426
427 return procFd;
428#endif
429}
static void FdRefer(int sysFd)
进程FD引用数改变
Definition: vfs_procfd.c:310
int GetAssociatedSystemFd(int procFd)
获取绑定的系统描述符
Definition: vfs_procfd.c:133
函数调用图:
这是这个函数的调用关系图:

◆ DisassociateProcessFd()

int DisassociateProcessFd ( int  procFd)

解绑系统文件描述符,返回系统文件描述符

在文件 vfs_procfd.c206 行定义.

207{
208 struct fd_table_s *fdt = GetFdTable();
209
210 if (!IsValidProcessFd(fdt, procFd)) {
211 return VFS_ERROR;
212 }
213
214 FileTableLock(fdt);
215 if (fdt->ft_fds[procFd].sysFd < 0) {//无系统文件描述符
216 FileTableUnLock(fdt);
217 return VFS_ERROR;//解绑失败
218 }
219 int sysFd = fdt->ft_fds[procFd].sysFd;//存在绑定关系
220 if (procFd >= MIN_START_FD) {//必须大于2
221 fdt->ft_fds[procFd].sysFd = -1;//解绑
222 }
223 FileTableUnLock(fdt);
224
225 return sysFd;
226}
函数调用图:
这是这个函数的调用关系图:

◆ FdClose()

static void FdClose ( int  sysFd,
unsigned int  targetPid 
)
static

关闭FD

在文件 vfs_procfd.c327 行定义.

328{
329 UINT32 intSave;
330
331 if ((sysFd > STDERR_FILENO) && (sysFd < CONFIG_NFILE_DESCRIPTORS)) {
332 LosProcessCB *processCB = OS_PCB_FROM_PID(targetPid);//获取目标进程
333 SCHEDULER_LOCK(intSave);
334 if (OsProcessIsInactive(processCB)) {
335 SCHEDULER_UNLOCK(intSave);
336 return;
337 }
338 SCHEDULER_UNLOCK(intSave);
339
340 files_close_internal(sysFd, processCB);//减少文件引用数(进程和系统的两个引用数)
341 }
342#if defined(LOSCFG_NET_LWIP_SACK)
343 if ((sysFd >= CONFIG_NFILE_DESCRIPTORS) && (sysFd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))) {
344 socks_close(sysFd);//减少sockert引用数
345 }
346#endif
347#if defined(LOSCFG_COMPAT_POSIX)
348 if ((sysFd >= MQUEUE_FD_OFFSET) && (sysFd < (MQUEUE_FD_OFFSET + CONFIG_NQUEUE_DESCRIPTORS))) {
349 mq_close((mqd_t)sysFd);//减少mqpersonal引用数
350 }
351#endif
352}
int files_close_internal(int fd, LosProcessCB *processCB)
int mq_close(mqd_t personal)
Definition: mqueue.c:550
UINTPTR mqd_t
Definition: mqueue.h:127
STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)
进程不活跃函数定义:身上贴有不使用且不活跃标签的进程
unsigned int UINT32
Definition: los_typedef.h:57
int socks_close(int sockfd)
Definition: sockets.c:1631
函数调用图:
这是这个函数的调用关系图:

◆ FdRefer()

static void FdRefer ( int  sysFd)
static

进程FD引用数改变

在文件 vfs_procfd.c310 行定义.

311{
312 if ((sysFd > STDERR_FILENO) && (sysFd < CONFIG_NFILE_DESCRIPTORS)) {
313 files_refer(sysFd);//增加系统FD引用次数
314 }
315#if defined(LOSCFG_NET_LWIP_SACK)
316 if ((sysFd >= CONFIG_NFILE_DESCRIPTORS) && (sysFd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))) {
317 socks_refer(sysFd);//增加socket引用次数
318 }
319#endif
320#if defined(LOSCFG_COMPAT_POSIX)
321 if ((sysFd >= MQUEUE_FD_OFFSET) && (sysFd < (MQUEUE_FD_OFFSET + CONFIG_NQUEUE_DESCRIPTORS))) {
322 MqueueRefer(sysFd);
323 }
324#endif
325}
void files_refer(int fd)
void MqueueRefer(int sysFd)
Definition: mqueue.c:339
void socks_refer(int sockfd)
Definition: sockets.c:1612
函数调用图:
这是这个函数的调用关系图:

◆ FileTableLock()

void FileTableLock ( struct fd_table_s fdt)

对进程文件表操作上锁

在文件 vfs_procfd.c40 行定义.

41{
42 /* Take the semaphore (perhaps waiting) */
43 while (sem_wait(&fdt->ft_sem) != 0) {
44 /*
45 * The only case that an error should occur here is if the wait was
46 * awakened by a signal.
47 */
48 LOS_ASSERT(errno == EINTR);
49 }
50}
sem_t ft_sem
Definition: fd_table.h:89
函数调用图:
这是这个函数的调用关系图:

◆ FileTableUnLock()

void FileTableUnLock ( struct fd_table_s fdt)

对进程文件表操作解锁

在文件 vfs_procfd.c52 行定义.

53{
54 int ret = sem_post(&fdt->ft_sem);
55 if (ret == -1) {
56 PRINTK("sem_post error, errno %d \n", get_errno());
57 }
58}
函数调用图:
这是这个函数的调用关系图:

◆ FreeProcessFd()

void FreeProcessFd ( int  procFd)

释放进程文件描述符

在文件 vfs_procfd.c191 行定义.

192{
193 struct fd_table_s *fdt = GetFdTable();
194
195 if (!IsValidProcessFd(fdt, procFd)) {
196 return;
197 }
198
199 FileTableLock(fdt);
200 FD_CLR(procFd, fdt->proc_fds); //相应位清0
201 FD_CLR(procFd, fdt->cloexec_fds);
202 fdt->ft_fds[procFd].sysFd = -1; //解绑系统文件描述符
203 FileTableUnLock(fdt);
204}
函数调用图:
这是这个函数的调用关系图:

◆ GetAssociatedSystemFd()

int GetAssociatedSystemFd ( int  procFd)

获取绑定的系统描述符

在文件 vfs_procfd.c133 行定义.

134{
135 struct fd_table_s *fdt = GetFdTable();//获取当前进程FD表
136
137 if (!IsValidProcessFd(fdt, procFd)) {
138 return VFS_ERROR;
139 }
140
141 FileTableLock(fdt);//锁表
142 if (fdt->ft_fds[procFd].sysFd < 0) {
143 FileTableUnLock(fdt);
144 return VFS_ERROR;
145 }
146 int sysFd = fdt->ft_fds[procFd].sysFd;//进程FD捆绑系统FD
147 FileTableUnLock(fdt);//解锁表
148
149 return sysFd;
150}
函数调用图:
这是这个函数的调用关系图:

◆ GetFdTable()

struct fd_table_s * GetFdTable ( void  )

获取进程文件描述符表

在文件 vfs_procfd.c77 行定义.

78{
79 struct fd_table_s *fdt = NULL;
80 struct files_struct *procFiles = OsCurrProcessGet()->files;//当前进程文件管理器
81
82 if (procFiles == NULL) {
83 return NULL;
84 }
85
86 fdt = procFiles->fdt;//进程文件表
87 if ((fdt == NULL) || (fdt->ft_fds == NULL)) {
88 return NULL;
89 }
90
91 return fdt;
92}
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
struct files_struct * files
struct fd_table_s * fdt
持有的文件表
Definition: fd_table.h:95
函数调用图:
这是这个函数的调用关系图:

◆ GetProcessFTable()

static struct fd_table_s * GetProcessFTable ( unsigned int  pid,
sem_t *  semId 
)
static

获取参数进程FD表

在文件 vfs_procfd.c354 行定义.

355{
356 UINT32 intSave;
357 struct files_struct *procFiles = NULL;
358 LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
359
360 SCHEDULER_LOCK(intSave);
361 if (OsProcessIsInactive(processCB)) {//参数进程必须处于激活状态
362 SCHEDULER_UNLOCK(intSave);
363 return NULL;
364 }
365
366 procFiles = processCB->files;
367 if (procFiles == NULL || procFiles->fdt == NULL) {
368 SCHEDULER_UNLOCK(intSave);
369 return NULL;
370 }
371
372 *semId = procFiles->fdt->ft_sem;
373 SCHEDULER_UNLOCK(intSave);
374
375 return procFiles->fdt;
376}
函数调用图:
这是这个函数的调用关系图:

◆ IsValidProcessFd()

static bool IsValidProcessFd ( struct fd_table_s fdt,
int  procFd 
)
static

在文件 vfs_procfd.c94 行定义.

95{
96 if (fdt == NULL) {
97 return false;
98 }
99 if ((procFd < 0) || (procFd >= fdt->max_fds)) {
100 return false;
101 }
102 return true;
103}
这是这个函数的调用关系图: