zoukankan      html  css  js  c++  java
  • FreeBSD内核之中的一个 ALQ机制的使用

    背景:

    笔者由于一个项目,这段时间在使用FreeBSD进行内核模块的编程。

    之前做过一段时间的Linux下驱动模块编程。对Linux下的模块编程还算熟悉。

    如今突然转到FreeBSD下。尽管Linux和FreeBSD两者都是类Unix系统。在实现机制上还是区别非常大的,多少有点不习惯。笔者的项目要在一个插入进内核的模块里。将log信息写入到磁盘的中。在用户层能够用读写文件的形式;在内核模块中,与Linux不同的是。并不推荐用户使用将这样的方法移植到内核模块中。

    可是FreeBSD却提供了一种ALQ机制。

    ALQ机制依赖于ALQ模块,在sys/conf/files中,能够看到它是可选的。

    简单介绍:

    ALQ(Asynchronous Logging Queues) 异步日志队列,提供了一种异步的定长和变长的record机制。

    它可以记录不论什么vnode。因此能对日志、字符设备及普通文件进行操作。

    全部的功能函数接受一个struct alq的參数,struct alq是一种隐含类型,维护一个ALQ的状态信息。这样的logging机制作为一个独立的内核线程来执行的,可以为系统全部的log请求服务。每个ale(asynchronous log entry)定义成一个struct ale,结构例如以下:

    <span style="font-size:12px;"><span style="font-size:10px;">	   struct ale {
    		   intptr_t	   ae_bytesused;   /* #	bytes written to ALE. */
    		   char		   *ae_data;	   /* Write ptr. */
    		   int		   ae_pad;	   /* Unused, compat. */
    	   };</span></span>
    一个alq能够以定长或变长的两种模式创建。可变长度的alq适应alq_writen()alq_getn()使用时写的长度。 而定长的alq在队列创建时就已经指定好了。定长模式如今已经被弃用,能够使用变模式来取代它。

    函数:

    #include <sys/alq.h>

    int alq_open_flags(struct alq **app, const char *file, struct ucred *cred, int cmode, int size, int flags);  创建一个可变长的alq。

    file为文件名称。

    假设文件不存在,alq_open()会试图创建它,而且cmode參数会被传递给alq_open()作为创建文件的属性。 对多数用户来说这个cmdode应被指定为ALQ_DEFAULT_CMODE。

    当打开文件和进行I/O操作时,cred參数指定信任证书。size设置队列的大小(单位为字节)。最后一个參数flag通常被设置成ALQ_ORDERED来 指明写线程等待忙碌的alq释放资源的顺序应该被保留。成功返回0,否则返回错误码(open(2))。

    int alq_open(struct alq **app,const char *file,struct ucred *cred, int cmode, int size, int count);被弃用的alq_open()封装在alq_open_flags()中。为了兼容老版本号。

    全部的 參数都是通过alq_open_flags()间接传递的。

    详细的我在此不作介绍,有兴趣的读者能够參考alq

    int alq_writen(struct alq *alq, void *data, int len, int flags);从data把len字节的数据写入到设置地可变长模式的alq中。假设alq_write()不能马上写  入这个数据,同一时候flags參    数又设置了ALQ_WAITOK。那么它将使用msleep_spin(9)睡眠等待数据。

    一个写操作会自己主动调度队列alq使 之写入磁盘。这样的行为能够通过给flags參数传递

    ALQ_NOACTIVATE。来控制它不会被写入磁盘。假设设置ALQ_NOWAIT或队列已满或系统关机,返回EWOULDBLOCK。

    int alq_write(struct alq *alq, void *data, int flags);被弃用的alq_write()封闭在alq_writen()中。有兴趣的读者能够參考alq

    void alq_flush(struct alq *alq);刷新alq到log文件。

    假设alq有数据可被刷新。而且没有没有进行在刷新。那么它将会堵塞。去进行IO操作。

    否则马上返回。

    void alq_close(struct alq *alq);关闭alq。刷新全部的挂起的写请求到log文件。释放申请的全部资源。
    struct ale * alq_getn(struct alq *alq, int len, int flags);从alq队列中返回一个ale。它会让alq处于锁定状态直到子alq_post()或alq_post_flags被调用。假设
    alq_getn()不能马上获取到len长度字节数据,而且在flags中设置了ALQ_WAITOK,它将会堵塞等待数据。调用者能够通过事先设置struct ale中的 ae_bytesused域,选择返回小于len字节到ale中。假设设置ALQ_NOWAIT或队列已满或系统关机,返回NULL。
    struct ale * alq_get(struct alq *alq, int flags); 被弃用。封装于alq_getn()中。
    void alq_post_flags(struct alq *alq, struct ale *ale, int flags);调度ale(从alq_getn()或alq_get()中获取)用于写alq。

    能够在flags參数中设置ALQ_NOACTIVATE指明队列不会马上被刷新到磁盘。 会对alq进行解锁。

    
    

    參考文献:

        ALQ
  • 相关阅读:
    HBase入门,看这一篇就够了
    【从零开始学CenterNet】6. CenterNet之loss计算代码解析
    cobbler使用DTK自动化做RAID
    linux批量免密登陆
    《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(下)
    《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(中)
    Python基础-v1
    js实现二维数组转置
    冰蝎3.0 流量特征分析 附特征
    关于 PDF相关整改建议的pdf后门事件分析
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6872425.html
Copyright © 2011-2022 走看看