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 释放资源。