hal_file.c

来自「基于ARM和uC/OS-II实现的串口控制台」· C语言 代码 · 共 134 行

C
134
字号
#include "../../inc/dev/hal_file.h"
#include "../../inc/pub/hal_errno.h"
#include "../../inc/pub/hal_types.h"
#include "../../inc/inf/hal_unistd_inf.h"
#include "../../inc/dev/hal_fcntl.h"
#include <stdio.h>
#include <string.h>

/*
 * hal_get_fd() 用于从文件描述符表中分配一个新的描述符,如果成功分配
 * 则配置该描述符中的dev元素指向dev参数所指定的器件
 */
int hal_get_fd (hal_dev* dev)
{
    hal_32 i;
    int rc = -EMFILE;
  
  /* 
   * 使用信号量hal_fd_list_lock来避免使用hal_fd_list表的冲突
   */
    HAL_SEM_PEND(hal_fd_list_lock, 0);
  
  /* 
   * 在文件描述符的数组中查找没用的单元,如果搜索到第一个没用的单元,则
   * 根据具体的情况更新变量"hal_max_fd", 这个变量用于指出现在所用的描述符
   * 中索引最大值,这样每次搜索的时候则可以知道从那个索引值以下是已用的,
   * 只在已用的描述符中搜索便可以实现提高效率之目的。 
   */

    for (i = 0; i < HAL_MAX_FD; i++)
    {
        if (!hal_fd_list[i].dev)
        {
            hal_fd_list[i].dev = dev;
            if (i > hal_max_fd)
            {
                hal_max_fd = i;
            }
            rc = i;
            goto hal_get_fd_exit;
        }
    }

    hal_get_fd_exit:

    HAL_SEM_POST(hal_fd_list_lock);

    return rc;
}

/*
 * hal_open_fd() 与 open()函数类似。但与open()函数不同,本函数不重新分配一个
 * 文件描述符,而是使用参数中传入的文件描述符。本函数主要由hal_io_redirect()
 * 函数调用,用于重定向stdin stdout stderr。在这里调用了open()函数的目的是
 * 防止无法打开设备时,不破害原来的文件描述符内容。
 */
static void hal_open_fd(hal_fd* fd, const char* name, int flags, int mode)
{
    int old;

    old = open(name, flags, mode);

    if (old >= 0)
    {
        fd->dev      = hal_fd_list[old].dev;
        fd->priv     = hal_fd_list[old].priv;
        fd->fd_flags = hal_fd_list[old].fd_flags;
        
        hal_release_fd (old);
    }
} 

/*
 * hal_io_redirect() 函数用于重定向stdout,stdin和stderr到指定的设备。 
 *
 * 在没调用本函数之前,stdin stdout stderr默认是指向/dev/null的。 
 * 如果本函数没调用成功,同样保持原来的指向。
 */
void hal_io_redirect(const char* stdout_dev, 
                     const char* stdin_dev, 
                     const char* stderr_dev)
{
  /* 重定向各个通道 */

  hal_open_fd (&hal_fd_list[STDOUT_FILENO], stdout_dev, O_WRONLY, 0777);
  hal_open_fd (&hal_fd_list[STDIN_FILENO], stdin_dev, O_RDONLY, 0777);
  hal_open_fd (&hal_fd_list[STDERR_FILENO], stderr_dev, O_WRONLY, 0777);
}  

/* 
 * hal_find_dev() 由open()函数调用,用于在已经注册的设备链表中根据名字查找
 * 相应的设备。参数llist是一个指向设备链表的头的指针。
 *
 * 没有匹配的设备,返回NULL,成功匹配返回对应设备的指针
 */
hal_dev* hal_find_dev(const char* name, hal_llist* llist)
{
    hal_dev* next = (hal_dev*) llist->next;
    hal_32 len;
    
    len  = strlen(name) + 1;
    
    
    while (next != (hal_dev*) llist)
    {
    
    
        if (!memcmp (next->name, name, len))
        {
            return next;  /*找到匹配的设备*/
        }
        next = (hal_dev*) next->llist.next;
    }
    
    /* 没有发现匹配 */
    
    return NULL;
}


/*
 * hal_release_fd() 用于释放一个文件描述符。注意为什么要fd>2才执行的原因是
 * 0 1 2所对应的文件描述符保留给stdin stdout stderr,不应该能释放。
 */

void hal_release_fd (int fd)
{
    if (fd > 2)
    {
        hal_fd_list[fd].fd_flags = 0;
        hal_fd_list[fd].dev      = 0;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?