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
  • 相关阅读:
    linux权限补充:rwt rwT rws rwS 特殊权限
    关于Linux操作系统下文件特殊权限的解释
    Java学习笔记——Java程序运行超时后退出或进行其他操作的实现
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 复数四则运算
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6872425.html
Copyright © 2011-2022 走看看