PROC 文件节点安装与移除

更新时间:
2024-03-14
下载文档

PROC 文件节点安装与移除

SylixOS 用户在安装或者移除 PROC 文件节点时,只需要使用系统提供的 API,使用方便简单。

PROC 文件节点安装和移除

创建和删除一个 PROC 文件节点

使用 API_ProcFsMakeNode 和 API_ProcFsRemoveNode 可以在 SylixOS 的/proc/下(即 procfs 根)创建和删除一个 PROC 节点。

#include <procFsLib.h>
INT  API_ProcFsMakeNode (PLW_PROCFS_NODE  p_pfsnNew,  CPCHAR  pcFatherName)

函数 API_ProcFsMakeNode 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • 参数 p_pfsnNew 表示新的节点控制块。
  • 参数 pcFatherName 表示父系节点名。

用户在添加 PROC 节点时注意,如果只是在/proc 下添加一个节点,那么 pcFatherName 表示的父系节点名为“/”(这个是 procfs 根),如果创建二级节点,父系节点名请以 procfs 根为起始路径。

说明:
PROC 内部是有的路径起始为 procfs 根,而非操作系统的根目录。

结构体 LW_PROCFS_NODE 是 PROC 节点类型,创建一个 PROC 节点之前需要填充好该结构体。

typedef struct lw_procfs_node {
    LW_LIST_LINE                   PFSN_lineBrother;           /*  兄弟节点              */
    struct lw_procfs_node         *PFSN_p_pfsnFather;          /*  父系节点              */
    PLW_LIST_LINE                  PFSN_plineSon;              /*  儿子节点              */
    PCHAR                          PFSN_pcName;                /*  节点名               */
    INT                            PFSN_iOpenNum;              /*  打开的次数            */
    BOOL                           PFSN_bReqRemove;            /*  是否请求删除          */
    VOIDFUNCPTR                    PFSN_pfuncFree;             /*  请求删除释放函数       */
    mode_t                         PFSN_mode;                  /*  节点类型             */
    time_t                         PFSN_time;                  /*  节点时间为当前时间     */
    uid_t                          PFSN_uid;
    gid_t                          PFSN_gid;
    PLW_PROCFS_NODE_OP             PFSN_p_pfsnoFuncs;          /*  文件操作函数          */
    LW_PROCFS_NODE_MSG             PFSN_pfsnmMessage;          /*  节点私有数据          */
#define PFSN_pvValue               PFSN_pfsnmMessage.PFSNM_pvValue
} LW_PROCFS_NODE;
typedef LW_PROCFS_NODE            *PLW_PROCFS_NODE;

该结构体中不是所有的信息都必须填写,如果不需要刻意填写 NULL 或者 0 即可。

#include <procFsLib.h>
INT  API_ProcFsRemoveNode (PLW_PROCFS_NODE  p_pfsn,  VOIDFUNCPTR  pfuncFree)

函数 API_ProcFsRemoveNode 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • 参数 p_pfsn 表示节点控制块。
  • 参数 pfuncFree 表示清除函数。

说明:
使用 API_ProcFsRemoveNode 删除一个 PROC 节点时要注意释放节点缓存或者其他资源。

获得 PROC 节点缓存指针

使用 API_ProcFsNodeBuffer 获取节点缓存指针,该节点缓存便是用来存储用户关心的可以在 PROC 中查看到的信息。如果事先没有为该 PROC 节点申请缓存,那么该节点缓存大小默认为 0。

#include <procFsLib.h>
PVOID  API_ProcFsNodeBuffer (PLW_PROCFS_NODE  p_pfsn)

函数 API_ProcFsNodeBuffer 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • 参数 p_pfsn 表示节点控制块。

申请和删除 PROC 节点缓存

API_ProcFsAllocNodeBuffer 申请节点缓存是从系统的堆中申请,所以使用结束后注意使用 API_ProcFsFreeNodeBuffer 释放资源。

#include <procFsLib.h>
INT  API_ProcFsAllocNodeBuffer (PLW_PROCFS_NODE  p_pfsn,  size_t  stSize)

函数 API_ProcFsAllocNodeBuffer 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • 参数 p_pfsn 表示节点控制块。
  • 参数 stSize 表示缓存大小。
#include <procFsLib.h>
INT  API_ProcFsFreeNodeBuffer (PLW_PROCFS_NODE  p_pfsn)

函数 API_ProcFsFreeNodeBuffer 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • 参数 p_pfsn 表示节点控制块。

procfs 设置和获得实际的 BUFFER 大小

#include <procFsLib.h>
VOID    API_ProcFsNodeSetRealFileSize(PLW_PROCFS_NODE      p_pfsn, 
                                      size_t               stRealSize)

函数 API_ProcFsNodeSetRealFileSize 原型分析:

  • 参数 p_pfsn 表示节点控制块。
  • 参数 stRealSize 表示实际文件内容大小。
#include <procFsLib.h>
size_t  API_ProcFsNodeGetRealFileSize (PLW_PROCFS_NODE  p_pfsn)

函数 API_ProcFsNodeGetRealFileSize 原型分析:

  • 此函数成功实际文件内容大小,失败返回 ERROR_NONE
  • 参数 p_pfsn 表示节点控制块。

程序展示了在 SylixOS 中添加和删除一个 PROC 节点,该节点名“acoinfo”。如以下程序所示。

#define  __SYLIXOS_STDIO
#define  __SYLIXOS_KERNEL
#include "../SylixOS/kernel/include/k_kernel.h"
#include "../SylixOS/system/include/s_system.h"
#include "procFs.h"

static ssize_t __procFsAcoinfoRead(PLW_PROCFS_NODE p_pfsn, PCHAR pcBuffer, size_t stMaxBytes, off_t oft);
static LW_PROCFS_NODE_OP _G_pfsAcoinfoFuncs = { __procFsAcoinfoRead, LW_NULL };
#define __PROCFS_BUFFER_SIZE_INFO       1024
static LW_PROCFS_NODE _G_pfsnModule[] = { LW_PROCFS_INIT_NODE("acoinfo", (S_IRUSR | S_IRGRP | S_IROTH | S_IFREG),
                                          &_G_pfsAcoinfoFuncs, "A", 0), };
static ssize_t __procFsAcoinfoRead(PLW_PROCFS_NODE p_pfsn, PCHAR pcBuffer, size_t stMaxBytes, off_t oft) 
{
    const CHAR cAcoinfoMsg[] ="\
    COMPANY               OS_NAME \n\
    -----------------   ----------------\n";
    PCHAR              pcFileBuffer;
    size_t             stRealSize;
    size_t             stCopeBytes;
    pcFileBuffer = (PCHAR) API_ProcFsNodeBuffer(p_pfsn);
    if (pcFileBuffer == LW_NULL) {
        size_t stNeedBufferSize = 0;
        stNeedBufferSize += sizeof(cAcoinfoMsg);
        stNeedBufferSize += 30;

        if (API_ProcFsAllocNodeBuffer(p_pfsn, stNeedBufferSize)) {
            _ErrorHandle(ENOMEM);
            return (0);
        }
        pcFileBuffer = (PCHAR) API_ProcFsNodeBuffer(p_pfsn);
        stRealSize = bnprintf(pcFileBuffer, stNeedBufferSize, 0, cAcoinfoMsg);
        stRealSize = bnprintf(pcFileBuffer, stNeedBufferSize,
                              sizeof(cAcoinfoMsg),"+ %12s   %11s\n", "ACOINFO", "SylixOS");
        API_ProcFsNodeSetRealFileSize(p_pfsn, stRealSize);
    } else {
           stRealSize = API_ProcFsNodeGetRealFileSize(p_pfsn);
    }
    if (oft >= stRealSize) {
        _ErrorHandle(ENOSPC);
        return (0);
    }

    stCopeBytes = __MIN(stMaxBytes, (size_t )(stRealSize - oft));     
    lib_memcpy(pcBuffer, (CPVOID) (pcFileBuffer + oft), (UINT) stCopeBytes);
    return ((ssize_t) stCopeBytes);
}

VOID __procFsAcoinfoInit(VOID) 
{
    API_ProcFsMakeNode(_G_pfsnModule, "/");
}

VOID __procFsAcoinfoExit(VOID) 
{
    if (API_ProcFsFreeNodeBuffer(_G_pfsnModule) < 0) {
        _DebugHandle(__ERRORMESSAGE_LEVEL,
        "Serious error: /proc/acoinfo file busy now, "
        "the system will become unstable!\r\n");
    }

    if (API_ProcFsRemoveNode(_G_pfsnModule, NULL)) {
        _DebugHandle(__ERRORMESSAGE_LEVEL,
        "Serious error: /proc/acoinfo file busy now, "
        "the system will become unstable!\r\n");
    }
}
#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>
#include <procModule.h>
int module_init (void)
{
    __procFsAcoinfoInit();
    return 0;
}
void module_exit (void)
{
    __procFsAcoinfoExit();
}

在 SylixOS 下运行:

# cd /lib/modules/
# ls
sperfs.ko       xsiipc.ko       acoinfo.ko      xinput.ko
# modulereg acoinfo.ko
module acoinfo.ko register ok, handle: 0x519a158
# cd /proc/
# ls
acoinfo             xinput              sysvipc          ksymbol          posix
net                 diskcache           power            fs               hook
smp                 cmdline             version          kernel           dma
cpuinfo             bspmem              self             pci              yaffs
# cat acoinfo
     COMPANY                   OS_NAME
-----------------------   ----------------------
+    ACOINFO                   SylixOS
# moduleunreg 0x519a158
module /lib/modules/acoinfo.ko unregister ok.
# ls
xinput              sysvipc             ksymbol             posix               net
diskcache           power               fs                  hook                smp
cmdline             version             kernel              dma                 cpuinfo
bspmem              self                pci                 yaffs

在卸载内核模块时在移除 PROC 节点之前,需要释放使用 API_ProcFsAllocNodeBuffer 申请的资源。所以在 API_ProcFsRemoveNode 移除 PROC 节点之前调用 API_ProcFsFreeNodeBuffer 释放资源。

文档内容是否对您有所帮助?
有帮助
没帮助