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;
}

2011年3月20日星期日

今天遇到的Ubuntu 10.04 Server 中的LANG设置问题

今天新申请了一个VPS,在其中安装了Ubuntu 10.04
第一次ssh登录上去,遇到这样的问题:
>adduser user

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:

看来是LANG设置有问题,查看一下:

root@www:~# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

网上google了一下,编辑/etc/default/locale

LANG="en_US.UTF-8"

再执行locale,情况相同。 装一个strace看看。(节选)

open("/usr/lib/locale/en_US.utf8/LC_CTYPE", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US/LC_CTYPE", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en.utf8/LC_CTYPE", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en/LC_CTYPE", O_RDONLY) = -1 ENOENT (No such file or directory)

看来en_US.utf8还没装呢。
网上google一下, 这个 http://romyli.javaeye.com/blog/853426 情况差不多,不过咱们这里情况更惨点,可以说什么locale都没装。

root@www:~# cd /usr/share/locales/
root@www:/usr/share/locales# ./install-language-pack en_US
Generating locales...
  en_US.UTF-8... done
Generation complete.
dpkg-trigger: dpkg-trigger must be called from a maintainer script (or with a --by-package option)


同样的方法,装上en_US
退出再重新ssh登录进去,看起来就正常了。
再找了一下,直接用 locale-gen 应该也可以。
root@www:~# locale-gen
Generating locales...
  en_US.UTF-8... up-to-date
Generation complete.

2011年3月6日星期日

互补的中西音乐(律)

题目写得挺大。

最近发现,一个新手用钢琴或者电子琴,能很容易的弹奏出中国古曲“沧海一声笑”。
如何弹奏呢,试着只按键盘上的黑键(就是那些半音的键)就好了。

钢琴或者电子琴是典型的西洋乐器,其音律应该是符合典型的西方乐律,是典型的七音乐器。
而“沧海一声笑”这样的古曲是典型的符合中国古典乐律的五音乐曲。

看起来中国五音和西洋的七音两者在十二律中可以说正好是一个互补关系。
生成这五音和七音的三分损益法和五度相生法也正好是兼容的。
某种意义上说,是否这也是中西方文化的关系呢?
也就是说 ,十二律是神来之物,算是一个音乐之总和吧。(十二也是一个特殊数字,比如一年十二个月)两种文化在此基础上各自选取了五音和七音,这两者正好能构成一种互补的关系。

当然,这只是说通常情况下,民间常见的形式。从“高技术”来说,中国古代也不是没有七音的乐律;西方应该也有其较为完整的乐律。

想到了,就记下了。欢迎指点探讨。