snifer

[原创]Blackfin ADSP 内核的新接口

0
阅读(2698)

今天和ADI一位大神探讨了Blackfin ADSP 内核的发展,主要说了随着接口的不断丰富,现有的内核该如何适应,我把我们的探讨内容写出来,和大家分享。

随着未来接口的不但丰富,访问用户空间的新的函数集初看起来可能有点令人失望,但它们的确使程序员的日子好过的多了。在Linux2.1上,不再需要显式地检查用户空间;access_ok一般不需要调用。使用新接口的代码可以直接进行数据传送。_ret函数在实现系统调用时证明是相当有用的,因为一个用户空间的失败通常导致系统调用的一个返回-EFAULT的失败。

因此,一个典型的read实现,看起来如下:

long new_read(struct inode *inode, struct file *filp, char *buf, unsigned long count);

{

/* identify your data (device-specific code) */

if (__copy_to_user(buf, new_data, count))

return -EFAULT;

return count;

}

注意使用不进行检查的__copy_to_user是因为调用者在把数据传输分派到文件操作之前已经检查了用户空间。这就象2.0,readwrite不需要调用verify_area

类似地,典型的ioctl实现看起来如下:

int new_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);

{

/* device-specific checks, if needed */

switch(cmd){

case NEW_GETVALUE:

put_user_ret(new_value, (int *)arg, -EFAULT);

break;

case NEW_SETVALUE:

get_user_ret(new_value, (int *)arg, -EFAULT);

default:

return –EINVAL;

}

return 0;

}

于版本2.0的对应者不同的是,这个函数在switch语句之前并不需要检查参数,因为每个get_userput_user会进行检查。另一种实现方式如下:

另一方面,当你想写可以同时在2.0和2.1上编译的代码时,问题变得稍微复杂一些,因为在老的核心上,你不能用C预处理器伪装新的行为。你不能简单地#define一个接收两个参数的get_user宏,因为实际的get_user实现在2.0中已经是个宏。

我在写既可移植有高效率的代码的选择是设置sysdep-2.1.h以提供具有下列函数的源码。下面只列出了读取数据的函数;写数据的函数行为完全一样。

int access_ok(type, address, size);

当在2.0上编译时,这个函数以verify_area的名义实现。

int verify_area_20(type, address, size);

通常,当为Linux2.1写代码时,你不需调用access_ok。另一方面,当在Linux2.0上编译时,则必须调用verify_area。这个函数就是要填平这个不同:当为Linux2.1编译时,它扩展为空;而为2.0编译时,它扩展为原来的verify_area。这个函数不能被称做verify_area,因为2.1已经有一个宏叫这个名字了。在2.1中定义的verify_area宏实现了access_ok的老的语义,它的存在是为了简化源码从2.0到2.1的转换。(从理论上说,你可以在你的模块中留下verify_area,只是将函数名改一下;这种简单移植技巧的缺点是新版本不能在2.0上编译。)

int GET_USER(var, add);

int __GET_USER(var, add);

GET_USER_RET(var, add, ret);

当在2.1上编译时,这些宏扩展为实际的get_user函数,即上面解释过的那些。当在2.0上编译时,get_user的2.0实现被用来实现与2.1中同样的功能。

int copy_from_user(to, from, size);

int __copy_from_user(to, from, size);

copy_from_user_ret(to, from, size);

当在2.0上编译时,这些扩展为memcpy_fromfs;而在2.1上,则使用本身的函数。_ret一类在2.0上从不会返回,因为复制函数不会失败。

我个人比较喜欢这种实现兼容性的方法,但这并不是唯一的方法。在我的示例代码中,任何用户空间的访问(除了用来readwrite的缓冲区,它们已经事先检查过了)之前,verify_area_20必须被调用。另一种方法更加忠实于2.1的语义,即当用2.0时,在每个get_usercopy_from_user之前自动生成一个verify_area。这个选择在源码级要更清晰一些,但在版本2.0上编译时效率相当低,包括代码大小和执行时间。

可以同时在2.0和2.1上编译的示例代码,如scull模块,可以在目录v2.1/scull中找到。

Blackfin ADSP在未来一定会有急速的发展,但是作为软硬件接口的操作系统会起到非常关键的作用,因此各位筒子们,这个领域潜力无限,如果你对这方面感兴趣,可以毫不犹豫的投入你的热情。

Baidu
map