- 论坛徽章:
- 0
|
翻译:山涛邮件:epost_guo@126.com
Driver porting:
miscellaneous changes
[Posted
February 11, 2003 by corbet]
This
article serves as a sort of final resting place for various small
changes in the kernel programming API which do not fit elsewhere.
这篇文章描述了内核API其他的一些细微的变化。
No more kdev_t
The kdev_t type has
been removed from the kernel; everything which works with device
numbers should now use the dev_t type. As part of this
change, dev_t has been expanded to 32 bits; 12 bits for the
major number, and 20 for the minor number.
If your driver uses the
i_rdev field of the inode structure, there are a
couple of new macros you can use:
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
Consider using these while
fixing your code; the next time the type of i_rdev changes,
you will be happier.
不再使用kdev_t
kdev_t类型已经从内核中移除,跟设备号相关的任何工作应当使用dev_t类型。作为这次改变的一部分,dev_t已经扩展到了32位:12位用于主设备号,20位用于次设备号。
如果你的驱动使用inode结构中的i_rdev域,你应当使用内核提供的下面一组宏从inode中获得主设备号和次设备号,而不是直接操作i_rdev:
[color="#008080"] unsigned int iminor(struct inode *inode);
[color="#008080"] unsigned int imajor(struct inode *inode);
这样修改代码,有利于你的代码有更好的移植性。当下次i_rdev类型发生变化了,你就很happy不用修改自己的代码了:)。
malloc.h
The include file
has long been a synonym for
. In 2.5, malloc.h was removed,
and all code should include slab.h directly.
头文件是的同义词,在2.5内核,malloc.h被移除,所有代码应当直接使用slab.h。
Designated
initializers
In the 2.3 development cycle,
much effort went into converting code to the (non-standard) gcc
designated initializer format for structures:
static struct some_structure = {
field1: value,
field2: value
};
In 2.5, the decision was made to
go to the ANSI C standard initializer format, and all of that code
was reworked again. The non-standard format still works, for now, but
it is worth the effort to make the change anyway. The standard format
looks like:
static struct some_structure = {
.field1 = value,
.field2 = value,
...
};
指定初始值
在2.3开发过程中,开发人员使用gcc的指定初始化格式来初始化结构体,象这样:
[color="#008080"] static struct some_structure = {
[color="#008080"] field1: value,
[color="#008080"] field2: value
[color="#008080"] };
但是这种格式并不是C语言的标准格式。
在2.5开发过程中,开发人员决定采用ANSI
C标准初始化格式来代替之前的gcc非标准格式。gcc非标准格式仍然可以工作,但是建议驱动开发者采用标准格式,象这样:
[color="#008080"] static struct some_structure = {
[color="#008080"] .field1 = value,
[color="#008080"] .field2 = value,
[color="#008080"] . . .
[color="#008080"] };
The min() and max() macros
A common step in the
development of most C programmers, shortly after they learn to
include stdio.h seems to be the definition of macros like:
#define max(a,b) ((a) > (b) ? (a) : (b))
In 2.5, it was noted that a
number of kernel developers had seemingly not moved beyond that
stage, and there was an unbelievable number of min() and
max() definitions sprinkled throughout the kernel source.
These definitions were not only redundant - they were unsafe. A max()
macro as defined above has the usual problem with side effects; it
also is not type-safe, especially when signed and unsigned values are
used.
Linus initially added his own
definition of min() and max() which added a third
argument - an explicit type. That change upset people badly enough
that some put substantial amounts of time into developing
two-argument versions that are type and side-effect safe. The result
now lives in , and should be used in
preference to any locally-defined version.
min()宏和max()宏
在大部分C开发人员的开发过程中,当他们的代码包含了stdio.h头文件时,就可以看见这样的宏定义:
[color="#008080"]#define max(a,b) ((a) > (b) ? (a) : (b))
在2.5内核开发中,有很多内核开发人员用这样的宏定义,内核代码里面有许多这样的定义。然而,这样的定义是不可重入的--它们不安全。上面所述的max()宏定义有副作用问题,而且它不是类型安全的,特别是当signed
和unsigned混合使用时。
Linus起初增加他自己的min()和max()定义时,他多使用了一个参数,这个参数表示数据的类型。这个改变使很多人厌烦,一些程序员花费时间开发出只带两个参数的版本,而且这个版本是无副作用和类型安全的。它们在上定义,所以我们在使用min()和max()时,应当优先使用上定义的版本,而不是自己代码中定义的版本。(译者:Corbet认为我们应该相信顶级内核开发人员所定义的版本,它们是没有任何问题的)
Dependent read
barriers
(Added February 24, 2003).
On most architectures, reads
from memory will not be reordered across a data dependency. Consider
this code fragment:
int *a, *b, x;
a = b;
x = *a;
Here, you would expect that *a
would yield the value pointed to by b; it would be
surprising to have the read of *a reordered in front of the
assignment to a. Some architectures can do just that sort of
reordering, however. One could ensure that such reordering does not
happen by inserting a rmb() (read memory barrier) between
the two assignment. But that would reduce performance needlessly on
many systems. So a new barrier, read_barrier_depends(), has
been added in this case. It should only be used in situations where
data dependencies exist. On architectures where data dependencies
will force ordering, read_barrier_depends() will do nothing.
On other architectures, it expands into a regular read barrier. See
this patch posting
for
more information.
读屏障(read
barrier)
在绝大多数的体系架构中,从内存中读数据会按照数据的倚赖关系顺序读取。思考下面的代码片段:
[color="#008080"] int *a, *b, x;
[color="#008080"] a = b;
[color="#008080"] x = *a;
这段代码里,你会期望*a的值是b指针所指向的变量的值。令人惊讶的是,某些系统会在给a赋值前先读取了*a,这是因为一些体系架构会重新调整代码的读取顺序。我们可以在两个赋值语句之间插入rmb()使得读取顺序不被打乱。但是这样会不必要的降低了许多系统的性能。因此,新开发的读屏障read_barrier_depends(),考虑到了这一点,它仅适用于存在数据倚赖的情况。当数据倚赖存在时必须被强制按顺序读取的体系架构中,read_barrier_depends()
什么也不做,而对于那些做法相反的体系架构(这些架构会打乱代码顺序,而不在乎数据倚赖的存在),read_barrier_depends()会扩展成一个真正的读屏障。
User-mode
helpers
(Added February 28, 2003).
The prototype of
call_usermodehelper() has changed:
int call_usermodehelper(char *path, char **argv, char **envp, int wait);
The new wait flag
controls whether call_usermodehelper() returns before the
user-mode process exits. If wait is set to a non-zero value,
the function will wait for the process to finish its work, and the
return value will be what the process itself returned. Otherwise the
return is immediate, and the return value only indicates whether the
user-mode process was successfully started or not.
Note that the older
exec_usermodehelper() function has been removed from the 2.5
kernel.
call_usermodehelper()
的原型发生了变化:
[color="#008080"] int call_usermodehelper(char *path, char **argv, char **envp, int wait);
新的wait
标志的作用是控制call_usermodehelper()
在user-mode
进程退出之前是否需要返回。如果wait被置为非0值,函数将等待直到user-mode进程结束,然后返回user-mode进程的返回值。如果wait被置为0,则函数立即返回,返回值表明了user-mode进程是否成功启动。
在2.5内核,旧的exec_usermodehelper()函数已被移除。
New
request_module() prototype
(Added May 20, 2003).
As of 2.5.70, the prototype
of request_module() has changed. This function now takes a
printf-style argument list. As a result, code which used to look
like:
char module_name[32];
sprintf(module_name, "foo-device-%d", number);
request_module(module_name);
can now be rewritten as:
request_module("foo-device-%d", number);
Most in-kernel code has already
been changed to do things the new way.
新的request_module()原型
在2.5.70版本里,request_module原型发生了改变。这个函数现在带上了打印信息。结果,以前的代码象这样:
[color="#008080"] char module_name[32];
[color="#008080"] sprintf(module_name, "foo-device-%d", number);
[color="#008080"] request_module(module_name);
现在被更改为这样:
[color="#008080"]equest_module("foo-device-%d", number);
现在绝大部分的内核代码都使用新的接口。
devfs
We'll not go into the details
here, but it is worth noting that devfs has been through extensive
changes, and will likely see more changes yet before 2.6.0 is
released. If your driver uses devfs, it will certainly need updating.
Note also that devfs has been
officially marked as "deprecated."
我们在这里不详细讨论devfs,但是值得说明的是devfs已经被大规模的进行了修改,我们可能在2.6.0
release的时候可以看到更多详细的修改内容。如果你的驱动使用devfs,它应当需要更新。
记住devfs已被官方声明“反对使用”。(译者:曾看过很多开发者对devfs的牢骚,现在devfs已被sysfs取代)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15620/showart_260868.html |
|