2011年10月26日星期三

Ubuntu 11.04中 VirtualBox 4.0 更新时遇到的问题及解决

最近在我的Ubuntu 11.04更新Linux Kernel时出现VirtualBox 4.0驱动升级失败的情况。

命令:
sudo /etc/init.d/vboxdrv setup

输出:

* Stopping VirtualBox kernel modules                                            *  done.
 * Uninstalling old VirtualBox DKMS kernel modules                               *  done.
 * Trying to register the VirtualBox kernel modules using DKMS                 
Error! Bad return status for module build on kernel: 2.6.38-12-generic (x86_64)
Consult the make.log in the build directory
/var/lib/dkms/vboxhost/4.0.0/build/ for more information.

 * Failed, trying without DKMS
 * Recompiling VirtualBox kernel modules                                       
 * Look at /var/log/vbox-install.log to find out what went wrong


试着手动编译,发现是VirtualBox试图使用linux/autoconf.h,而在较新的Kernel中此文件更改了路径。

解决方法如下:

cd /usr/src/linux-headers-2.6.38-12-generic/include/linux
sudo ln -s ../generated/autoconf.h .
sudo /etc/init.d/vboxdrv setup

对于不同的Linux Kernel 版本,应使用对应的/usr/src下的路径名。

2011年10月14日星期五

一个简单的ringbuffer (circular buffer) 程序(C语言)

最近需要在使用一个ringbuffer,用于缓冲音频数据。
数据在两个线程之间传递。按说是很简单的功能,但合用的C库还不太好找。
找了一下,看到合适一点的库也是GPL的,不太适合我用在闭源工程中,于是自己重新写了一个简单的,以LGPL方式发行。

功能比较简单,数据分块,每次读或写一个块。
块大小和块数量在ringbuffer初始化时设定。
同时仅支持一个reader和一个writer。

测试环境:
ARM Linux, gcc 4.1.1, uClibc

代码附在后面,其使用方法:

initialize:
    rb_t *rbuf = rb_open(chunk_size, chunk_count);

reader:

    while(rb_read_ok(rb,buf)==false){
        idle_task();
    }

writer:

    while(rb_write_ok(rb,buf)==false){
        idle_task();
    }

deinitialize:

    rb_close(rbuf);

 
ringbuf.h:
#pragma once
#include <stdint.h>
#include <stdbool.h>

struct rb_s;
typedef struct rb_s rb_t;

rb_t *rb_open(unsigned int size, unsigned int count);
void rb_reset(rb_t *rb);
void rb_close(rb_t *rb);
bool rb_writable(rb_t *rb);
bool rb_readable(rb_t *rb);
bool rb_write_ok(rb_t *rb, const void *data);
bool rb_read_ok(rb_t *rb, void *buf);


ringbuf.c:

#include <malloc.h>
#include <string.h>
#include "ringbuf.h"
struct rb_s{
    unsigned int size;
    unsigned int count;
    unsigned int rptr, wptr;
    unsigned char *buf;
};

rb_t *rb_open(unsigned int size, unsigned int count)
{
    rb_t *rb = calloc(1, sizeof(rb_t));
    rb->buf = calloc(count, size);
    if(rb->buf==NULL){
        free(rb);
        return NULL;
    }
    rb->size = size;
    rb->count = count;
    return rb;
}
void rb_reset(rb_t *rb)
{
    rb->wptr = 0;
    rb->rptr = 0;
}

void rb_close(rb_t *rb)
{
    if(rb){
        free(rb->buf);
        memset(rb,0, sizeof(rb_t));
        free(rb);
    }
}

bool rb_writable(rb_t *rb)
{
    unsigned int wptr = rb->wptr;
    wptr++;
    if(wptr>=rb->count) wptr = 0;
    if(wptr == rb->rptr) return false;
    return true;
}

bool rb_readable(rb_t *rb)
{
    if(rb->wptr==rb->rptr) return false;
    return true;
}

bool rb_write_ok(rb_t *rb, const void *data)
{
    if(rb_writable(rb)){
        memcpy(rb->buf+rb->size*rb->wptr,data, rb->size);
        rb->wptr++;
        if(rb->wptr == rb->count) rb->wptr = 0;
        return true;
    }
    return false;
}

bool rb_read_ok(rb_t *rb, void *buf)
{
    if(rb_readable(rb)){
        memcpy(buf, rb->buf+rb->size*rb->rptr, rb->size);
        rb->rptr++;
        if(rb->rptr == rb->count) rb->rptr = 0;
        return true;
    }
    return false;
}