内核源码学习:Linux 2.4内核API(一)
2008-09-18 14:10
驱动程序的基本函数
类别
函数名
功能
函数形成
参数
描述
驱动程序入口和出口点
module_init
驱动程序初始化入口点
module_init ( x)
x为启动时或插入模块时要运行的函数
如果在启动时就确认把这个驱动程序 插入内核或以静态形成链接,则module_init 将其初始化例程加入到"__initcall.int"代码段,否则将用init_module封装其初始化例程,以便该驱动程序作为模块来使用。
module_exit
驱动程序退出出口点
module_exit ( x)
x为驱动程序被卸载时要运行的函数
当驱动程序是一个模块,用rmmod卸载一个模块时module_exit()将用cleanup_module()封装clean-up代码。如果驱动程序是静态地链接进内核,则module_exit()函数不起任何作用。
原子和指针操作
atomic_read
读取原子变量
atomic_read ( v)
v为指向atomic_t类型的指针
原子地读取v的值。注意要保证atomic的有用范围只有24位。
atomic_set
设置原子变量
atomic_set ( v, i)
v为指向atomic_t类型的指针,i为待设置的值
原子地把v的值设置为i。注意要保证atomic的有用范围只有24位。
atomic_add
把整数增加到原子变量
void atomic_add (int i, atomic_t * v)
i为要增加的值,v为指向atomic_t类型的指针。
原子地把i 增加到v。注意要保证atomic的有用范围只有24位。
atomic_sub
减原子变量的值
void atomic_sub (int i, atomic_t * v)
i为要减取的值,v为指向atomic_t类型的指针。
原子地从v减取i。注意要保证atomic的有用范围只有24位。
atomic_sub_and_test
从变量中减去值,并测试结果
int atomic_sub_and_test (int i, atomic_t * v)
i为要减取的值,v为指向atomic_t类型的指针。
原子地从v减取i的值,如果结果为0,则返回真,其他所有情况都返回假。注意要保证atomic的有用范围只有24位。
atomic_inc
增加原子变量的值
void atomic_inc (atomic_t * v)
v为指向atomic_t类型的指针。
原子地从v减取1。注意要保证atomic的有用范围只有24位。
atomic_dec
减取原子变量的值
void atomic_dec (atomic_t * v)
v为指向atomic_t类型的指针。
原子地给v增加1。注意要保证atomic的有用范围只有24位。
atomic_dec_and_test
减少和测试
int atomic_dec_and_test (atomic_t * v)
v为指向atomic_t类型的指针。
原子地给v减取1,如果结果为0,则返回真,其他所有情况都返回假。注意要保证atomic的有用范围只有24位。
atomic_inc_and_test
增加和测试
int atomic_ inc _and_test (atomic_t * v)
v为指向atomic_t类型的指针。
原子地给v增加1,如果结果为0,则返回真,其他所有情况都返回假。注意要保证atomic的有用范围只有24位。
atomic_add_negative
如果结果为负数,增加并测试
int atomic_add_negative (int i, atomic_t * v)
i为要减取的值,v为指向atomic_t类型的指针。
原子地给v增加i,如果结果为负数,则返回真,如果结果大于等于0,则返回假。注意要保证atomic的有用范围只有24位。
et_unaligned
从非对齐位置获取值
get_unaligned ( ptr)
ptr指向获取的值
这个宏应该用来访问大于单个字节的值,该值所处的位置不在按字节对齐的位置,例如从非u16对齐的位置检索一个u16的值。注意,在某些体系结构中,非对齐访问要化费较高的代价。
put_unaligned
把值放在一个非对齐位置
put_unaligned ( val, ptr)
val为要放置的值,ptr指向要放置的位置
这个宏用来把大于单个字节的值放置在不按字节对齐的位置,例如把一个u16值写到一个非u16对齐的位置。注意事项同上。
延时、调度及定时器例程
schedule_timeout
睡眠到定时时间到
signed long schedule_timeout (signed long timeout)
timeout为以jiffies为单位的到期时间
使当前进程睡眠,直到所设定的时间到期。如果当前进程的状态没有进行专门的设置,则睡眠时间一到该例程就立即返回。如果当前进程的状态设置为:
TASK_UNINTERRUPTIBLE:则睡眠到期该例程返回0
‚ TASK_INTERRUPTIBLE:如果当前进程接收到一个信号,则该例程就返回,返回值取决于剩余到期时间。
当该例程返回时,要确保当前进程处于TASK_RUNNING状态。
内核源码学习:Linux 2.4内核API(二)
2008-09-18 14:11
双向循环链表的操作
函数名
功能
函数形成
参数
描述
list_add
增加一个新元素
void list_add (struct list_head * new, struct list_head * head)
new为要增加的新元素,head为增加以后的链表头
在指定的头元素后插入一个新元素,用于栈的操作。
list_add_tail
增加一个新元素
void list_add_tail (struct list_head * new, struct list_head * head);
new为要增加的新元素,head为增加以前的链表头
在指定的头元素之前插入一个新元素,用于队列的操作。
list_del
从链表中删除一个元素
void list_del (struct list_head * entry);
entry为要从链表中删除的元素
list_del_init
从链表删除一个元素,并重新初始化链表
void list_del_init (struct list_head * entry)
entry为要从链表中删除的元素
list_empty
测试一个链表是否为空
int list_empty (struct list_head * head)
head为要测试的链表
list_splice
把两个链表合并在一起
void list_splice (struct list_head * list, struct list_head * head)
list为新加入的链表,head为第一个链表
list_entry
获得链表中元素的结构
list_entry ( ptr, type, member)
ptr为指向list_head的指针,type为一个结构体,而member为结构type中的一个域,其类型为list_head。
list_for_each
扫描链表
list_for_each ( pos, head)
pos为指向list_head的指针,用于循环计数,head为链表头。
内核源码学习:Linux 2.4内核API(三)
2008-09-18 14:18
基本C库函数
当编写驱动程序时,一般情况下不能使用C标准库的函数。Linux内核也提供了与标准库函数功能相同的一些函数,但二者还是稍有差别。
类别
函数名
功能
函数形成
参数
描述
字符串转换
simple_strtol
把一个字符串转换为一个有符号长整数
long simple_strtol (const char * cp, char ** endp, unsigned int base)
cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。
simple_strtoll
把一个字符串转换为一个有符号长长整数
long long simple_strtoll (const char * cp, char ** endp, unsigned int base)
cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。
simple_strtoul
把一个字符串转换为一个无符号长整数
long long simple_strtoul (const char * cp, char ** endp, unsigned int base)
cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。
simple_strtoull
把一个字符串转换为一个无符号长长整数
long long simple_strtoull (const char * cp, char ** endp, unsigned int base)
cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。
vsnprintf
格式化一个字符串,并把它放在缓存中。
int vsnprintf (char * buf, size_t size, const char * fmt, va_list args)
buf为存放结果的缓冲区, size为缓冲区的大小,fmt为要使用的格式化字符串,args为格式化字符串的参数。
snprintf
格式化一个字符串,并把它放在缓存中。
int snprintf (char * buf, size_t size, const char * fmt, ... ...)
buf为存放结果的缓冲区, size为缓冲区的大小,fmt为格式化字符串,使用@…来对格式化字符串进行格式化,…为可变参数。
vsprintf
格式化一个字符串,并把它放在缓存中。
int vsprintf (char * buf, const char * fmt, va_list args)
buf为存放结果的缓冲区, size为缓冲区的大小,fmt为要使用的格式化字符串,args为格式化字符串的参数。
sprintf
格式化一个字符串,并把它放在缓存中。
int sprintf (char * buf, const char * fmt, ... ...)
buf为存放结果的缓冲区, size为缓冲区的大小,fmt为格式化字符串,使用@…来对格式化字符串进行格式化,…为可变参数。
内核源码学习:Linux 2.4内核API(四)
2008-09-18 14:19
符串操作
strcpy
拷贝一个以NUL结束的字符串
char * strcpy (char * dest, const char * src)
dest为目的字符串的位置, src为源字符串的位置。
strncpy
拷贝一个定长的、以NUL结束的字符串
char * strncpy (char * dest, const char * src, size_t count)
dest为目的字符串的位置, src为源字符串的位置,count为要拷贝的最大字节数
与用户空间的strncpy不同,这个函数并不用NUL填充缓冲区,如果与源串超过count,则结果以非NUL结束
strcat
把一个以NUL结束的字符串添加到另一个串的末尾
char * strcat (char * dest, const char * src)
dest为要添加的字符串, src为源字符串。
strncat
把一个定长的、以NUL结束的字符串添加到另一个串的末尾
char * strncat (char * dest, const char * src, size_t count)
dest为要添加的字符串, src为源字符串,count为要拷贝的最大字节数
注意,与strncpy,形成对照, strncat正常结束。
strchr
在一个字符串中查找第一次出现的某个字符
char * strchr (const char * s, int c)
s为被搜索的字符串,c为待搜索的字符。
strrchr
在一个字符串中查找最后一次出现的某个字符
char * strrchr (const char * s, int c)
s为被搜索的字符串,c为待搜索的字符。
strlen
给出一个字符串的长度
size_t strlen (const char * s)
s为给定的字符串
strnlen
给出给定长度字符串的长度
size_t strnlen (const char * s, size_t count)
s为给定的字符串
strpbrk
在一个字符串中查找第一次出现的一组字符
char * strpbrk (const char * cs, const char * ct)
cs为被搜索的字符串,ct为待搜索的一组字符
strtok
把一个字符串分割为子串
char * strtok (char * s, const char * ct)
s为被搜索的字符串,ct为待搜索的子串
注意,一般不提倡用这个函数,而应当用strsep
memset
用给定的值填充内存区
void * memset (void * s, int c, size_t count)
s为指向内存区起始的指针,c为 要填充的内容,count为内存区的大小
I/O空间的访问不能使用memset,而应当使用memset_io。
bcopy
把内存的一个区域拷贝到另一个区域
char * bcopy (const char * src, char * dest, int count)
src为源字符串,dest为目的字符串,而count为内存区的大小
注意,这个函数的功能与memcpy相同,这是从BSD遗留下来的,对I/O空间的访问应当用memcpy_toio或 memcpy_fromio
memcpy
把内存的一个区域拷贝到另一个区域
void * memcpy (void * dest, const void * src, size_t count)
dest为目的字符串,Src为源字符串,而count为内存区的大小
对I/O空间的访问应当用memcpy_toio或 memcpy_fromio
memmove
把内存的一个区域拷贝到另一个区域
void * memmove (void * dest, const void * src, size_t count)
dest为目的字符串,Src为源字符串,而count为内存区的大小
memcpy和memmove处理重叠的区域,而该函数不处理。
memcmp
比较内存的两个区域
int memcmp (const void * cs, const void * ct, size_t count)
cs为一个内存区,ct为另一个内存区,而count为内存区的大小
memscan
在一个内存区中查找一个字符
void * memscan (void * addr, int c, size_t size)
addr为内存区,c为要搜索的字符,而size为内存区的大小
返回c第一次出现的地址,如果没有找到c,则向该内存区传递一个字节。
strstr
在以NUL结束的串中查找第一个出现的子串
char * strstr (const char * s1, const char * s2)
s1为被搜索的串,s2为待搜索的串。
memchr
在一个内存区中查找一个字符
void * memchr (const void * s, int c, size_t n)
s为内存区,为待搜索的字符,n为内存的大小
返回c第一次出现的位置,如果没有找到c,则返回空。
内核源码学习:Linux 2.4内核API(五)
2008-09-18 14:21
位操作
set_bit
在位图中原子地设置某一位
void set_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址
这个函数是原子操作,如果不需要原子操作,则调用__set_bit函数,nr可以任意大,位图的大小不限于一个字。
__set_bit
在位图中设置某一位
void __set_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址
clear_bit
在位图中清某一位
void clear_bit (int nr, volatile void * addr)
nr为要清的位,addr为位图的起始地址
该函数是原子操作,但不具有加锁功能,如果要用于加锁目的,应当调用smp_mb__before_clear_bit 或smp_mb__after_clear_bit函数,以确保任何改变在其他的处理器上是可见的。
__change_bit
在位图中改变某一位
void __change_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址。
与change_bit不同,该函数是非原子操作。
change_bit
在位图中改变某一位
void change_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址。
test_and_set_bit
设置某一位并返回该位原来的值
int test_and_set_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址。
该函数是原子操作
__test_and_set_bit
设置某一位并返回该位原来的值
int __test_and_set_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址。
该函数是非原子操作,如果这个操作的两个实例发生竞争,则一个成功而另一个失败,因此应当用一个锁来保护对某一位的多个访问。
test_and_clear_bit
清某一位,并返回原来的值
int test_and_clear_bit (int nr, volatile void * addr);
nr为要设置的位,addr为位图的起始地址。
该函数是原子操作
__test_and_clear_bit
清某一位,并返回原来的值
int __test_and_clear_bit (int nr, volatile void * addr);
nr为要设置的位,addr为位图的起始地址。
该函数为非原子操作
test_and_change_bit
改变某一位并返回该位的新值
int test_and_change_bit (int nr, volatile void * addr)
nr为要设置的位,addr为位图的起始地址。
该函数为原子操作
test_bit
确定某位是否被设置
int test_bit (int nr, const volatile void * addr)
nr为要测试的第几位,addr为位图的起始地址。
find_first_zero_bit
在内存区中查找第一个值为0的位
int find_first_zero_bit (void * addr, unsigned size)
addr为内存区的起始地址,size为要查找的最大长度
返回第一个位为0的位号
find_next_zero_bit
在内存区中查找第一个值为0的位
int find_next_zero_bit (void * addr, int size, int offset)
addr为内存区的起始地址,size为要查找的最大长度,offset开始搜索的起始位号。
ffz
在字中查找第一个0
unsigned long ffz (unsigned long word);
word为要搜索的字。
ffs
查找第一个已设置的位
int ffs (int x)
x为要搜索的字。
这个函数的定义方式与Libc中的一样。
hweight32
返回一个N位字的加权平衡值
hweight32 ( x)
x为要加权的字
一个数的加权平衡是这个数所有位的总和。
内核源码学习:Linux 2.4内核API(六)
2008-09-18 14:22
Linux内存管理中Slab缓冲区
函数名
功能
函数形成
参数
描述
kmem_cache_create
创建一个缓冲区
kmem_cache_t * kmem_cache_create (const char * name, size_t size, size_t offset, unsigned long flags, void (*ctor) (void*, kmem_cache_t *, unsigned long), void (*dtor) (void*, kmem_cache_t *, unsigned long));
Name为在/proc/slabinfo中标识这个缓冲区的名字;size
为在这个缓冲区中创建对象的大小;offset为页中的位移量;flags为Slab标志;ctor
和dtor分别为构造和析构对象的函数。
成功则返回指向所创建缓冲区的指针,失败则返回空。不能在一个中断内调用该函数,但该函数的执行过程可以被中断。当通过该缓冲区分配新的页面时ctor运行,当页面被还回之前dtor运行。
kmem_cache_shrink
缩小一个缓冲区
int kmem_cache_shrink (kmem_cache_t * cachep)
Cachep为要缩小的缓冲区
为缓冲区释放尽可能多的Slab。为了有助于调试,返回0意味着释放所有的Slab。
kmem_cache_destroy
删除一个缓冲区
int kmem_cache_destroy (kmem_cache_t * cachep);
cachep为要删除的缓冲区
从Slab缓冲区删除kmem_cache_t 对象,成功则返回0。
这个函数应该在卸载模块时调用。调用者必须确保在kmem_cache_destroy执行期间没有其他对象再从该缓冲区分配内存。
kmem_cache_alloc
分配一个对象
void * kmem_cache_alloc (kmem_cache_t * cachep, int flags);
cachep为要删除的缓冲区,flags请参见kmalloc()
从这个缓冲区分配一个对象。只有当该缓冲区没有可用对象时,才用到标志flags。
kmalloc
分配内存
void * kmalloc (size_t size, int flags)
size为所请求内存的字节数,flags为要分配的内存类型
kmalloc 是在内核中分配内存常用的一个函数。flags 参数的取值如下:
GFP_USER – 代表用户分配内存,可以睡眠。
GFP_KERNEL – 分配内核中的内存,可以睡眠
GFP_ATOMIC – 分配但不睡眠,在中断处理程序内部使用。
另外,设置GFP_DMA标志表示所分配的内存必须适合DMA,例如在i386平台上,就意味着必须从低16MB分配内存。
kmem_cache_free
释放一个对象
void kmem_cache_free (kmem_cache_t * cachep, void * objp)
cachep为曾分配的缓冲区,objp为曾分配的对象。
释放一个从这个缓冲区中曾分配的对象
kfree
释放以前分配的内存
void kfree (const void * objp)
objp为由kmalloc()返回的指针
内核源码学习:Linux 2.4内核API(七)
2008-09-18 14:28
Linux中的VFS
类别
函数名
功能
函数形成
参数
描述
目录
项缓存
d_invalidate
使一个目录项无效
int d_invalidate (struct dentry * dentry)
dentry为要无效的目录项
如果通过这个目录项能够到达其他的目录项,就不能删除这个目录项,并返回-EBUSY。如果该函数操作成功,则返回0。
d_find_alias
找到索引节点一个散列的别名
struct dentry * d_find_alias (struct inode *
inode为要讨论的索引节点
如果 inode 有一个散列的别名,就获取对这个别名,并返回它,否则返回空。注意,如果inode 是一个目录,就只能有一个别名,如果它没有子目录,就不能进行散列。
prune_dcache
裁减目录项缓存
void prune_dcache (int count)
count为要释放的目录项的一个域
缩小目录项缓存。当需要更多的内存,或者仅仅需要卸载某个安装点(在这个安装点上所有的目录项都不使用),则调用该函数。
如果所有的目录项都在使用,则该函数可能失败。
shrink_dcache_sb
为一个超级块而缩小目录项缓存
void shrink_dcache_sb (struct super_block * sb)
sb为超级块
为一个指定的超级块缩小目录缓存。在卸载一个文件系统是调用该函数释放目录缓存。
have_submounts
检查父目录或子目录是否包含安装点
int have_submounts (struct dentry * parent)
parent为要检查的目录项
如果parent或它的子目录包含一个安装点,则该函数返回真。
shrink_dcache_parent
裁减目录项缓存
void shrink_dcache_parent (struct dentry * parent)
parent为要裁减目录项的父目录项
裁减目录项缓存以删除父目录项不用的子目录项。
d_alloc
分配一个目录项
struct dentry * d_alloc (struct dentry * parent, const struct qstr * name)
parent为要分配目录项的父目录项,name为指向qstr结构的指针。
分配一个目录项。如果没有足够可用的内存,则返回NULL。成功则返回目录项。
d_instantiate
为一个目录项填充索引节点信息
void d_instantiate (struct dentry * entry, struct inode * inode)
entry为要完成的目录项,inode为这个目录项的inode。
在目录项中填充索引节点的信息。注意,这假定 inode的 count域已由调用者增加,以表示inode正在由该目录项缓存使用。
d_alloc_root
分配根目录项
struct dentry * d_alloc_root (struct inode * root_inode)
root_inode为要给根分配的inode。
为给定的inode分配一个根("/") 目录项,该in ode被实例化并返回。如果没有足够的内存或传递的inode参数为空,则返回空。
d_lookup
查找一个目录项
struct dentry * d_lookup (struct dentry * parent, struct qstr * name)
parent为父目录项,name为要查找的目录项名字的qstr结构。
为name搜索父目录项的子目录项。如果该目录项找到,则它的引用计数加1,并返回所找到的目录项。调用者在完成了对该目录项的使用后,必须调用d_put释放它。
d_validate
验证由不安全源所提供的目录项
int d_validate (struct dentry * dentry, struct dentry * dparent)
dentry是dparent有效的子目录项,dparent是父目录项(已知有效)
一个非安全源向我们发送了一个dentry,在这里,我们要验证它并调用dget。该函数由ncpfs用在readdir的实现。如果dentry无效,则返回0。
d_delete
删除一个目录项
void d_delete (struct dentry * dentry)
dentry为要删除的目录项
如果可能,把该目录项转换为一个负的目录项,否则从哈希队列中移走它以便以后的删除。
内核源码学习:Linux 2.4内核API(八)
2008-09-18 14:29
d_rehash
给哈希表增加一个目录项
void d_rehash (struct dentry * entry)
dentry为要增加的目录项
根据目录项的名字向哈希表增加一个目录项
d_move
移动一个目录项
void d_move (struct dentry * dentry, struct dentry * target)
dentry为要移动的目录项,target为新目录项
更新目录项缓存以反映一个文件名的移动。目录项缓存中负的目录项不应当以这种方式移动。
__d_path
返回一个目录项的路径
char * __d_path (struct dentry * dentry, struct vfsmount * vfsmnt, struct dentry * root, struct vfsmount * rootmnt, char * buffer, int buflen)
dentry为要处理的目录项,vfsmnt为目录项所属的安装点,root为根目录项,rootmnt为根目录项所属的安装点,buffer为返回值所在处,buflen为buffer的长度。
把一个目录项转化为一个字符串路径名。如果一个目录项已被删除,串“(deleted)”被追加到路径名,注意这有点含糊不清。返回值放在buffer中。
"buflen"应该为页大小的整数倍。调用者应该保持dcache_lock锁。
is_subdir
新目录项是否是父目录项的子目录
int is_subdir (struct dentry * new_dentry, struct dentry * old_dentry)
new_dentry为新目录项,
old_dentry为旧目录项。
如果新目录项是父目录的子目录项(任何路径上),就返回1,否则返回0。
find_inode_number
检查给定名字的目录项是否存在
ino_t find_inode_number (struct dentry * dir, struct qstr * name)
dir为要检查的目录,name
为要查找的名字。
对于给定的名字,检查这个目录项是否存在,如果该目录项有一个inode,则返回其索引节点号,否则返回0。
d_drop
删除一个目录项
void d_drop (struct dentry * dentry)
dentry为要删除的目录项
d_drop从父目录项哈希表中解除目录项的哈希连接,以便通过VFS的查找再也找不到它。注意这个函数与d_delete的区别,d_delete尽可能地把目录项表记为负的,查找时会得到一个负的目录项,而d_drop会使查找失败。
d_add
向哈希队列增加目录项
void d_add (struct dentry * entry, struct inode * inode)
dentry为要增加的目录项,inode为与目录项对应的索引节点。
该函数将把目录项加到哈希队列,并初始化inode。这个目录项实际上已在d_alloc()函中得到填充。
dget
获得目录项的一个引用
struct dentry * dget (struct dentry * dentry)
dentry为要获得引用的目录项
给定一个目录项或空指针,如果合适就增加引用count的值。当一个目录项有引用时(count不为0),就不能删除这个目录项。引用计数为0的目录项永远也不会调用dget。
d_unhashed
检查目录项是否被散列
int d_unhashed (struct dentry * dentry)
dentry为要检查的目录项
如果通过参数传递过来的目录项没有用哈希函数散列过,则返回真。
内核源码学习:Linux 2.4内核API(九)
2008-09-18 14:29
索引节点处理
__mark_inode_dirty
使索引节点“脏”
void __mark_inode_dirty (struct inode * inode, int flags)
inode为要标记的索引节点,flags为标志,应当为I_DIRTY_SYNC
这是一个内部函数,调用者应当调用mark_inode_dirty 或mark_inode_dirty_sync。
write_inode_now
向磁盘写一个索引节点
void write_inode_now (struct inode * inode, int sync)
inode为要写到磁盘的索引节点,sync表示是否需要同步。
如果索引节点为脏,该函数立即把它写到给磁盘。主要由knfsd来使用。
clear_inode
清除一个索引节点
void clear_inode (struct inode * inode)
inode为要写清除的索引节点
由文件系统来调用该函数,告诉我们该索引节点不再有用。
invalidate_inodes
丢弃一个设备上的索引节点
int invalidate_inodes (struct super_block * sb);
sb为超级块
对于给定的超级块,丢弃所有的索引节点。如果丢弃失败,说明还有索引节点处于忙状态,则返回一个非0值。如果丢弃成功,则超级块中所有的节点都被丢弃。
get_empty_inode
获得一个索引节点
struct inode * get_empty_inode ( void)
无
这个函数的调用发生在诸如网络层想获得一个无索引节点号的索引节点,或者文件系统分配一个新的、无填充信息的索引节点。
成功则返回一个指向inode的指针,失败则返回一个NULL指针。返回的索引节点不在任何超级块链表中。
iunique
获得一个唯一的索引节点号
ino_t iunique (struct super_block * sb, ino_t max_reserved)
sb为超级块,max_reserved为最大保留索引节点号
对于给定的超级块,获得该系统上一个唯一的索引节点号。这一般用在索引节点编号不固定的文件系统中。返回的节点号大于保留的界限但是唯一。
注意,如果一个文件系统有大量的索引节点,则这个函数会很慢。
insert_inode_hash
把索引节点插入到哈希表
void insert_inode_hash (struct inode * inode)
inode为要插入的索引节点
把一个索引节点插入到索引节点的哈希表中,如果该节点没有超级块,则把它加到一个单独匿名的链中。
remove_inode_hash
从哈希表中删除一个索引节点
void remove_inode_hash (struct inode * inode)
inode为要删除的索引节点
从超级块或匿名哈希表中删除一个索引节点
iput
释放一个索引节点
void iput (struct inode * inode)
inode为要释放的索引节点
如果索引节点的引用计数变为0,则释放该索引节点,并且可以撤销它。
bmap
在一个文件中找到一个块号
int bmap (struct inode * inode, int block)
inode为文件的索引节点,block为要找的块。
返回设备上的块号,例如,寻找索引节点1的块4,则该函数将返回相对于磁盘起始位置的盘块号。
update_atime
更新访问时间
void update_atime (struct inode * inode)
inode为要访问的索引节点
更新索引节点的访问时间,并把该节点标记为写回。这个函数自动处理只读文件系统、介质、“noatime”标志以及具有“noatime”标记者的索引节点。
make_bad_inode
由于I/O错误把一个索引节点标记为坏
void make_bad_inode (struct inode * inode)
inode为要标记为坏的索引节点
由于介质或远程网络失败而造成不能读一个索引节点时,该函数把该节点标记为“坏”,并引起从这点开始的I/O操作失败。
is_bad_inode
是否是一个错误的inode
int is_bad_inode (struct inode * inode)
inode为要测试的索引节点
如果要测试的节点已标记为坏,则返回真。
注册以及超级块
register_filesystem
注册一个新的文件系统
int register_filesystem (struct file_system_type * fs)
fs为指向文件系统结构的指针
把参数传递过来的文件系统加到文件系统的链表中。成功则返回0,失败则返回一个负的错误码。
unregister_filesystem
注销一个文件系统
int unregister_filesystem (struct file_system_type * fs)
fs为指向文件系统结构的指针
把曾经注册到内核中的文件系统删除。如果没有找到个文件系统,则返回一个错误码,成功则返回0。
这个函数所返回的file_system_type结构被释放或重用。
get_super
获得一个设备的超级块
struct super_block * get_super (kdev_t dev)
dev为要获得超级块的设备
扫描超级块链表,查找在给定设备上安装的文件系统的超级块。如果没有找到,则返回空。
内核源码学习:Linux 2.4内核API(十)
2008-09-18 14:33
Linux的连网
套接字缓冲区函数
函数名
功能
函数形成
参数
描述
skb_queue_empty
检查队列是否为空
int skb_queue_empty (struct sk_buff_head * list)
list为队列头
如果队列为空返回真,否则返回假
skb_get
引用缓冲区
struct sk_buff * skb_get (struct sk_buff * skb)
skb为要引用的缓冲区
对套接字缓冲区再引用一次,返回指向缓冲区的指针
kfree_skb
释放一个sk_buff
void kfree_skb (struct sk_buff * skb)
sk为要释放的缓冲区
删除对一个缓冲区的引用,如果其引用计数变为0,则释放它
skb_cloned
缓冲区是否是克隆的
int skb_cloned (struct sk_buff * skb)
skb为要检查的缓冲区
如果以skb_clone标志来产生缓冲区,并且是缓冲区多个共享拷贝中的一个,则返回真。克隆的缓冲区具有共享数据,因此在正常情况下不必对其进行写。
skb_shared
缓冲区是否是共享的
int skb_shared (struct sk_buff * skb)
skb为要检查的缓冲区
如果有多于一个的人引用这个缓冲区就返回真。
skb_share_check
检查缓冲区是否共享的,如果是就克隆它
struct sk_buff * skb_share_check (struct sk_buff * skb, int pri)
skb为要检查的缓冲区,pri为内存分配的优先级
如果缓冲区是共享的,就克隆这个缓冲区,并把原来缓冲区的引用计数减1,返回新克隆的缓冲区。如果不是共享的,则返回原来的缓冲区。当从中断状态或全局锁调用该函数时,pri必须是GFP_ATOMIC。
内存分配失败则返回NULL。
skb_unshare
产生一个共享缓冲区的拷贝
struct sk_buff * skb_unshare (struct sk_buff * skb, int pri);
skb为要检查的缓冲区,pri为内存分配的优先级
如果套接字缓冲区是克隆的,那么这个函数就创建一个新的数据拷贝,并把原来缓冲区的引用计数减1,返回引用计数为1的新拷贝。如果不是克隆的,就返回原缓冲区。当从中断状态或全局锁调用该函数时,pri必须是GFP_ATOMIC。
内存分配失败则返回NULL。
skb_queue_len
获得队列的长度
__u32 skb_queue_len (struct sk_buff_head * list_)
list_为测量的链表
返回&sk_buff 队列的指针。
__skb_queue_head
在链表首部对一个缓冲区排队
void __skb_queue_head (struct sk_buff_head * list, struct sk_buff * newsk)
list为要使用的链表,
newsk为要排队的缓冲区。
在链表首部对一个缓冲区进行排队。这个函数没有锁,因此在调用它之前必须持有必要的锁。一个缓冲区不能同时放在两个链表中。
skb_queue_head
在链表首部对一个缓冲区排队
void skb_queue_head (struct sk_buff_head * list, struct sk_buff * newsk)
list为要使用的链表,
newsk为要排队的缓冲区。
在链表首部对一个缓冲区进行排队。这个函持有锁,因此可以安全地使用。一个缓冲区不能同时放在两个链表中。
__skb_queue_tail
在链表尾部对一个缓冲区排队
void __skb_queue_tail (struct sk_buff_head * list, struct sk_buff * newsk)
list为要使用的链表,
newsk为要排队的缓冲区。
在链表尾部对一个缓冲区进行排队。这个函数没有锁,因此在调用它之前必须持有必要的锁。一个缓冲区不能同时放在两个链表中。
skb_queue_tail
在链表尾部对一个缓冲区排队
void skb_queue_tail (struct sk_buff_head * list, struct sk_buff * newsk)
list为要使用的链表,
newsk为要排队的缓冲区。
在链表尾部对一个缓冲区进行排队。这个函持有锁,因此可以安全地使用。一个缓冲区不能同时放在两个链表中。
__skb_dequeue
从队列的首部删除一个缓冲区
struct sk_buff * __skb_dequeue (struct sk_buff_head * list)
list为要操作的队列
删除链表首部。这个函数不持有任何锁,因此使用时应当持有适当的锁。如果队链表为空则返回NULL,成功则返回首部元素。
skb_dequeue
从队列的首部删除一个缓冲区
struct sk_buff * skb_dequeue (struct sk_buff_head * list)
list为要操作的队列
删除链表首部,这个函数持有锁,因此可以安全地使用。如果队链表为空则返回NULL,成功则返回首部元素。
skb_insert
插入一个缓冲区
void skb_insert (struct sk_buff * old, struct sk_buff * newsk)
old为插入之前的缓冲区,newsk为要插入的缓冲区
把一个数据包放在链表中给定的包之前。该函数持有链表锁,并且是原子操作。一个缓冲区不能同时放在两个链表中。
内核源码学习:Linux 2.4内核API(十一)
2008-09-18 14:47
skb_append
追加一个缓冲区
void skb_append (struct sk_buff * old, struct sk_buff * newsk)
old为插入之前的缓冲区,newsk为要插入的缓冲区
把一个数据包放在链表中给定的包之前。该函数持有链表锁,并且是原子操作。一个缓冲区不能同时放在两个链表中。
skb_unlink
从链表删除一个缓冲区
void skb_unlink (struct sk_buff * skb);
Skb为要删除的缓冲区
把一个数据包放在链表中给定的包之前。该函数持有链表锁,并且是原子操作。
_skb_dequeue_tail
从队尾删除
struct sk_buff * __skb_dequeue_tail (struct sk_buff_head * list)
List为要操作的链表
从链表尾部删除。这个函数不持有任何锁,因此必须持以合适的锁来使用。如果链表为空,则返回NULL,成功则返首部元素。
skb_dequeue_tail
从队头删除
struct sk_buff * skb_dequeue_tail (struct sk_buff_head * list)
List为要操作的链表
删除链表尾部,这个函数持有锁,因此可以安全地使用。如果队链表为空则返回NULL,成功则返回首部元素。
skb_put
把数据加到缓冲区
unsigned char * skb_put (struct sk_buff * skb, unsigned int len)
skb为要使用的缓冲区,len为要增加的数据长度
这个函数扩充缓冲区所使用的数据区。如果扩充后超过缓冲区总长度,内核会产生警告。函数返回的指针指向所扩充数据的第一个字节。
skb_push
把数据加到缓冲区的开始
unsigned char * skb_push (struct sk_buff * skb, unsigned int len);
skb为要使用的缓冲区,len为要增加的数据长度
这个函数扩充在缓冲区的开始处缓冲区所使用的数据区。如果扩充后超过缓冲区首部空间的总长度,内核会产生警告。函数返回的指针指向所扩充数据的第一个字节。
skb_pull
从缓冲区的开始删除数据
unsigned char * skb_pull (struct sk_buff * skb, unsigned int len)
skb为要使用的缓冲区,len为要删除的数据长度
这个函数从链表开始处删除数据,把腾出的内存归还给首部空间。把指向下一个缓冲区的指针返回。
skb_headroom
缓冲区首部空闲空间的字节数
int skb_headroom (const struct sk_buff * skb)
skb为要检查的缓冲区
返回&sk_buff首部空闲空间的字节数
skb_tailroom
缓冲区尾部的空闲字节数
int skb_tailroom (const struct sk_buff * skb)
skb为要检查的缓冲区
返回&sk_buff尾部空闲空间的字节数
skb_reserve
调整头部的空间
void skb_reserve (struct sk_buff * skb, unsigned int len)
skb为要改变的缓冲区,len为要删除的字节数
通过减少尾部空间,增加一个空&sk_buff的首部空间。这仅仅适用于空缓冲区。
skb_trim
从缓冲区删除尾部
void skb_trim (struct sk_buff * skb, unsigned int len);
skb为要改变的缓冲区,len为新的长度
通过从尾部删除数据,剪切缓冲区的长度。如果缓冲区已经处于指定的长度,则不用改变。
skb_orphan
使一个缓冲区成为孤儿
void skb_orphan (struct sk_buff * skb);
skb是要成为孤儿的缓冲区
如果一个缓冲区当前有一个拥有者,我们就调用拥有者的析构函数,使skb没有拥有者。该缓冲区继续存在,但以前的拥有者不再对其“负责”。
skb_queue_purge
使一个链表空
void skb_queue_purge (struct sk_buff_head * list)
list为要腾空的链表
删除在&sk_buff链表上的所有缓冲区。这个函数持有链表锁,并且是原子的。
__skb_queue_purge
使一个链表空
void __skb_queue_purge (struct sk_buff_head * list);
list为要腾空的链表
删除在&sk_buff链表上的所有缓冲区。这个函数不持有链表锁,调用者必须持有相关的锁来使用它。
dev_alloc_skb
为发送分配一个skbuff
struct sk_buff * dev_alloc_skb (unsigned int length)
Length为要分配的长度
分配一个新的&sk_buff,并赋予它一个引用计数。这个缓冲区有未确定的头空间。用户应该分配自己需要的头空间。
如果没有空闲内存,则返回NULL。尽管这个函数是分配内存,但也可以从中断来调用。
skb_cow
当需要时拷贝skb的首部
struct sk_buff * skb_cow (struct sk_buff * skb, unsigned int headroom)
Skb为要拷贝的缓冲区,headroom为需要的头空间
如果传递过来的缓冲区缺乏足够的头空间或是克隆的,则该缓冲区被拷贝,并且附加的头空间变为可用。如果没有空闲的内存,则返回空。如果缓冲区拷贝成功,则返回新的缓冲区,否则返回已存在的缓冲区。
skb_over_panic
私有函数
void skb_over_panic (struct sk_buff * skb, int sz, void * here)
skb为缓冲区,sz为大小,here为地址。
用户不可调用。
skb_under_panic
私有函数
void skb_under_panic (struct sk_buff * skb, int sz, void * here)
skb为缓冲区,sz为大小,here为地址。
用户不可调用。
内核源码学习:Linux 2.4内核API(十二)
2008-09-18 14:48
alloc_skb
分配一个网络缓冲区
struct sk_buff * alloc_skb (unsigned int size, int gfp_mask)
size为要分配的大小,gfp_mask为分配掩码
分配一个新的&sk_buff。返回的缓冲区没有size大小的头空间和尾空间。新缓冲区的引用计数为1。返回值为一缓冲区,如果失败则返回空。从中断分配缓冲区,掩码只能使用GFP_ATOMIC的gfp_mask。
__kfree_skb
私有函数
void __kfree_skb (struct sk_buff * skb)
skb为缓冲区
释放一个sk_buff。释放与该缓冲区相关的所有事情,清除状态。这是一个内部使用的函数,用户应当调用kfree_skb。
skb_clone
复制一个sk_buff
struct sk_buff * skb_clone (struct sk_buff * skb, int gfp_mask)
skb为要克隆的缓冲区,gfp_mask为分配掩码。
复制一个&sk_buff。新缓冲区不是由套接字拥有。两个拷贝共享相同的数据包而不是结构。新缓冲区的引用计数为1。如果分配失败,函数返回NULL,否则返回新的缓冲区。如果从中断调用这个函数,掩码只能使用GFP_ATOMIC的gfp_mask。
skb_copy
创建一个sk_buff的私有拷贝
struct sk_buff * skb_copy (const struct sk_buff * skb, int gfp_mask)
skb为要拷贝的缓冲区,gfp_mask为分配优先级。
既拷贝&sk_buff也拷贝其数据。该函数用在调用者希望修改数据并需要数据的私有拷贝来进行改变时。失败返回NULL,成功返回指向缓冲区的指针。
返回的缓冲区其引用计数为1。如果从中断调用,则必须传递的优先级为GFP_ATOMIC。
skb_copy_expand
拷贝并扩展sk_buff
struct sk_buff * skb_copy_expand (const struct sk_buff * skb, int
newheadroom, int newtailroom, int gfp_mask);
skb为要拷贝的缓冲区,newheadroom为头部的新空闲字节数,newtailroom为尾部的新空闲字节数。
既拷贝&sk_buff也拷贝其数据,同时分配额外的空间。当调用者希望修改数据并需要对私有数据进行改变,以及给新的域更多的空间时调用该函数。失败返回NULL,成功返回指向缓冲区的指针。
返回的缓冲区其引用计数为1。如果从中断调用,则必须传递的优先级为GFP_ATOMIC。
内核源码学习:Linux 2.4内核API(十三)
2008-09-18 14:53
网络设备支持
驱动程序的支持
函数名
功能
函数形成
参数
描述
init_etherdev
注册以太网设备
truct net_device * init_etherdev (struct net_device * dev, int sizeof_priv)
dev为要填充的以太网设备结构,或者要分配一个新的结构时为NULL,sizeof_priv是为这个以太网设备要分配的额外私有结构的大小。
用以太网的通用值填充这个结构的域。如果传递过来的dev为NULL,则构造一个新的结构,包括大小为sizeof_priv的私有数据区。强制将这个私有数据区在32字节(不是位)上对齐。
dev_add_pack
增加数据包处理程序
void dev_add_pack (struct packet_type * pt)
pt为数据包类型
把一个协议处理程序加到网络栈,把参数传递来的&packet_type链接到内核链表中。
dev_remove_pack
删除数据包处理程序
void dev_remove_pack (struct packet_type * pt)
pt为数据包类型
删除由dev_add_pack曾加到内核的协议处理程序。把&packet_type 从内核链表中删除,一旦该函数返回,这个结构还能再用。
__dev_get_by_name
根据名字找设备
struct net_device * __dev_get_by_name (const char * name);
name为要查找的名字
根据名字找到一个接口。必须在RTNL 信号量或dev_base_lock锁的支持下调用。如果找到这个名字,则返回指向设备的指针,如果没有找到,则返回NULL。引用计数器并没有增加,因此调用者必须小心地持有锁。
dev_get_by_name
根据名字找设备
struct net_device * dev_get_by_name (const char * name)
name为要查找的名字
根据名字找到一个接口。这个函数可以在任何上下文中调用并持有自己的锁。返回句柄的引用计数增加,调用者必须在其不使用时调用dev_put释放它,如果没有匹配的名字,则返回NULL。
dev_get
测试设备是否存在
int dev_get (const char * name)
name为要测试的名字
测试名字是否存在。如果找到则返回真。为了确保在测试期间名字不被分配或删除,调用者必须持有rtnl信号量。这个函数主要用来与原来的驱动程序保持兼容。
__dev_get_by_index
根据索引找设备
struct net_device * __dev_get_by_index (int ifindex)
ifindex为设备的索引
根据索引搜索一个接口。如果没有找到设备,则返回NULL,找到则返回指向设备的指针。该设备的引用计数没有增加,因此调用者必须小心地关注加锁,调用者必须持有RTNL 信号量或dev_base_lock锁。
dev_get_by_index
根据名字找设备
struct net_device * dev_get_by_index (int ifindex)
ifindex为设备的索引
根据索引搜索一个接口。如果没有找到设备,则返回NULL,找到则返回指向设备的指针。所返回设备的引用计数加1,因此,在用户调用dev_put释放设备之前,返回指针是安全的。
dev_alloc_name
为设备分配一个名字
int dev_alloc_name (struct net_device * dev, const char * name)
dev为设备,name 为格式化字符串。
传递过来一个格式化字符串,例如ltd,该函数试图找到一个合适的 id。设备较多时这是很低效的。调用者必须在分配名字和增加设备时持有dev_base 或 rtnl锁,以避免重复。返回所分配的单元号或出错返回一个复数。
dev_alloc
分配一个网络设备和名字
struct net_device * dev_alloc (const char * name, int * err)
name 为格式化字符串,err为指向错误的指针
传递过来一个格式化字符串,例如ltd,函数给该名字分配一个网络设备和空间。如果没有可用内存,则返回NULL。如果分配成功,则名字被分配,指向设备的指针被返回。如果名字分配失败,则返回NULL,错误的原因放在err指向的变量中返回。调用者必须在做这一切时持有dev_base 或 RTNL锁,以避免重复分配名字。
netdev_state_change
设备改变状态
void netdev_state_change (struct net_device * dev)
name 为引起通告的设备
当一个设备状态改变时调用该函数。
dev_load
装入一个网络模块
void dev_load (const char * name)
name 为接口的名字
如果网络接口不存在,并且进程具有合适的权限,则这个函数装入该模块。如果在内核中模块的装入是不可用的,则装入操作就变为空操作。
dev_open
为使用而准备一个接口
int dev_open (struct net_device * dev)
device为要打开的设备
以从低层到上层的过程获得一个设备。设备的私有打开函数被调用,然后多点传送链表被装入,最后设备被移到上层,并把NETDEV_UP信号发送给网络设备的notifier chain。
在一个活动的接口调用该函数只能是个空操作。失败则返回一个负的错误代码。
内核源码学习:Linux 2.4内核API(十四)
2008-09-18 14:56
dev_close
关闭一个接口
int dev_close (struct net_device * dev)
dev为要关闭的设备
这个函数把活动的设备移到关闭状态。向网络设备的notifier chain发送一个NETDEV_GOING_DOWN。然后把设备变为不活动状态,并最终向notifier chain发NETDEV_DOWN信号。
register_netdevice_notifier
注册一个网络通告程序块
int register_netdevice_notifier (struct notifier_block * nb)
nb为通告程序
当网络设备的事件发生时,注册一个要调用的通告程序。作为参数传递来的通告程序被连接到内核结构,在其被注销前不能重新使用它。失败则返回一个负的错误码。
unregister_netdevice_notifier
注销一个网络通告块
int unregister_netdevice_notifier (struct notifier_block * nb)
nb为通告程序
取消由register_netdevice_notifer曾注册的一个通告程序。把这个通告程序从内核结构中解除,然后还可以重新使用它。失败则返回一个负的错误码。
dev_queue_xmit
传送一个缓冲区
int dev_queue_xmit (struct sk_buff * skb)
skb为要传送的缓冲区
为了把缓冲区传送到一个网络设备,对缓冲区进行排队。调用者必须在调用这个函数前设置设备和优先级,并建立缓冲区。该函数也可以从中断中调用。失败返回一个负的错误码。成功并不保证帧被传送,因为也可能由于拥塞或流量调整而撤销这个帧。
netif_rx
把缓冲区传递到网络协议层
void netif_rx (struct sk_buff * skb)
skb为要传送的缓冲区
这个函数从设备驱动程序接受一个数据包,并为上层协议的处理对其进行排队。该函数总能执行成功。在处理期间,可能因为拥塞控制而取消这个缓冲区。
net_call_rx_atomic
void net_call_rx_atomic(void(fn) (void))
fn为要调用的函数
使一个函数的调用就协议层而言是原子的。
register_gifconf
注册一个SIOCGIF处理程序
int register_gifconf (unsigned int family, gifconf_func_t * gifconf)
family为地址组,gifconf为处理程序
注册由地址转储例程决定的协议。当另一个处理程序替代了由参数传递过来的处理程序时,才能释放或重用后者。
netdev_set_master
建立主/从对
int netdev_set_master (struct net_device * slave, struct net_device *
master)
slave为从设备,master为主设备。
改变从设备的主设备。传递NULL以中断连接。调用者必须持有RTNL信号量。失败返回一个负错误码。成功则调整引用计数,RTM_NEWLINK发送给路由套接字,并且返回0。
dev_set_allmulti
更新设备上多个计数
void dev_set_allmulti (struct net_device * dev, int inc)
dev为设备,inc为修改者。
把接收的所有多点传送帧增加到设备或从设备删除。当设备上的引用计数依然大于0时,接口保持着对所有接口的监听。一旦引用计数变为0,设备回转到正常的过滤操作。负的inc值用来在释放所有多点传送需要的某个资源时减少其引用计数。
dev_ioctl
网络设备的ioctl
int dev_ioctl (unsigned int cmd, void * arg)
cmd为要发出的命令,arg为用户空间指向ifreq结构的指针。
向设备发布ioctl函数。这通常由用户空间的系统调用接口调用,但有时也用作其他目的。返回值为一个正数,则表示从系统调用返回,为负数,则表示出错。
dev_new_index
分配一个索引
int dev_new_index ( void)
无
为新的设备号返回一个合适而唯一的值。调用者必须持有rtnl信号量以确保它返回唯一的值。
netdev_finish_unregister
完成注册
int netdev_finish_unregister (struct net_device * dev)
dev为设备。
撤销或释放一个僵死的设备。成功返回0。
unregister_netdevice
从内核删除设备
int unregister_netdevice (struct net_device * dev)
dev为设备。
这个函数关闭设备接口并将其从内核表删除。成功返回0,失败则返回一个负数。
内核源码学习:Linux 2.4内核API(十五)
2008-09-18 15:02
8390网卡
ei_open
打开/初始化网板
int ei_open (struct net_device * dev)
dev为要初始化的网络设备。
尽管很多注册的设备在每次启动时仅仅需要设置一次,但这个函数在每次打开设备时还彻底重新设置每件事。
ei_close
关闭网络设备
int ei_close (struct net_device * dev)
dev为要关闭的网络设备。
ei_open的相反操作,在仅仅在完成“ifconfigdown”时使用
ei_interrupt
处理来自8390的中断
void ei_interrupt (int irq, void * dev_id, struct pt_regs * regs);
irq为中断号,dev_id为指向net_devicede 指针,regs没有使用。
处理以太网接口中断。我们通过网卡指定的函数从8390取回数据包,并在网络栈触发它们。如果需要,我们也处理传输的完成并激活传输路径。我们也根据需要更新计数器并处理其他的事务。
ethdev_init
初始化8390设备结构的其余部分
int ethdev_init (struct net_device * dev)
dev为要初始化的网络设备结构。
初始化8390设备结构的其余部分。不要用__init(),因为这也由基于8390的模块驱动程序使用。
NS8390_init
初始化8390硬件
void NS8390_init (struct net_device * dev, int startp)
dev为要初始化的设备,startp为布尔值,非0启动芯片处理。
必须持以
内核源码学习:Linux 2.4内核API(十六)
2008-09-18 15:03
模块支持
模块装入
函数名
功能
函数形成
参数
描述
request_module
试图装入一个内核模块
int request_module (const char * module_name)
module_name为模块名
使用用户态模块装入程序装入一个模块。成功返回0,失败返回一个负数。注意,一个成功的装入并不意味着这个模块在自己出错时就能卸载和退出。调用者必须检查他们所提出的请求是可用的,而不是盲目地调用。
如果自动装入模块的功能被启用,那么这个函数就不起作用。
call_usermodehelper
启动一个用户态的应用程序
int call_usermodehelper (char * path, char ** argv, char ** envp);
path为应用程序的路径名,argv为以空字符结束的参数列表,envp为以空字符结束的环境列表。
运行用户空间的一个应用程序。该应用程序被异步启动。它作为keventd的子进程来运行,并具有root的全部权能。Keventd在退出时默默地获得子进程。
必须从进程的上下文中调用该函数,成功返回0,失败返回一个负数。
内部模块支持
inter_module_register
注册一组新的内部模块数据
void inter_module_register (const char * im_name, struct module * owner, const void * userdata)
im_name为确定数据的任意字符串,必须唯一,owner为正在注册数据的模块,通常用THIS_MODULE ,userdata指向要注册的任意用户数据。
检查im_name还没有被注册,如果已注册就发出“抱怨”。对新数据,则把它追加到inter_module_entry链表。
inter_module_unregister
注销一组内部模块数据
void inter_module_unregister (const char * im_name)
im_name为确定数据的任意字符串,必须唯一。
检查im_name已经注册,如果没有注册就发出“抱怨”。 对现有的数据,则把它从inter_module_entry链表中删除。
inter_module_get
从另一模块返回任意的用户数据
const void * inter_module_get (const char * im_name)
im_name为确定数据的任意字符串,必须唯一。
如果im_name还没有注册,则返回NULL。增加模块拥有者的引用计数,如果失败则返回NULL,否则返回用户数据。
inter_module_get_request
内部模块自动调用request_module
const void * inter_module_get_request (const char * im_name, const char * modname)
im__name为确定数据的任意字符串,必须唯一;modname为期望注册m_name的模块。
如果inter_module_get失败,调用request_module,然后重试。
inter_module_put
释放来自另一个模块的数据
void inter_module_put (const char * im_name)
im__name为确定数据的任意字符串,必须唯一。
如果im_name还没有被注册,则“抱怨”,否则减少模块拥有者的引用计数。
内核源码学习:Linux 2.4内核API(十七)
2008-09-18 15:03
块设备
函数名
功能
函数形式
参数
描述
其他
blk_cleanup_queue
当不再需要一个请求队列时,释放一个request_queue_t
void blk_cleanup_queue (request_queue_t * q);
q为要释放的请求队列。
blk_cleanup_queue与blk_init_queue是成对出现的。应该在释放请求队列时调用该函数;典型的情况是块设备正被注销时调用。该函数目前的主要任务是释放分配到队列中所有的struct request结构。
低级驱动程序有希望首先完成任何重要的请求…
blk_queue_headactive
指明请求队列的头是否可以是活跃的。
void blk_queue_headactive (request_queue_t * q, int active)
q为这次申请的队列,active为一个标志,表示队列头在哪儿是活跃的。
块设备驱动程序可以选定把当前活动请求留在请求队列,只有在请求完成时才移走它。队列处理例程为安全起见把这种情况假定为缺省值,并在请求被撤销时,将不再在合并或重新组织请求时包括请求队列的头。
如果驱动程序在处理请求之前从队列移走请求,它就可以在合并和重新安排中包含队列头。这可以通过以active标志为0来调用blk_queue_headactive。
如果一个驱动程序一次处理多个请求,它必须从请求队列移走他们(或至少一个)。
当一个队列被插入,则假定该队列头为不活跃的。
blk_queue_make_request
为设备定义一个交替的make_request 函数。
void blk_queue_make_request (request_queue_t * q, make_request_fn * mfn)
q为受影响设备的请求队列,mfn为交替函数。
把buffer_heads结构传递到设备驱动程序的常用方式为让驱动程序把请求收集到请求队列,然后让驱动程序准备就绪时把请求从那个队列移走。这种方式对很多块设备驱动程序很有效。但是,有些块设备(如虚拟设备md或lvm)并不是这样,而是把请求直接传递给驱动程序,这可以通过调用 blk_queue_make_request()函数来达到。
按以上方式操作的驱动程序必须能够恰当地处理在“高内存”的缓冲区,这是通过调用 bh_kmap 获得一个内核映射,或通过调用 create_bounce 在常规内存创建一个缓冲区。
blk_init_queue
为块设备的使用准备一个请求队列。
void blk_init_queue (request_queue_t * q, request_fn_proc * rfn)
q为要初始化的请求队列,rfn为处理请求所调用的函数。
如果一个块设备希望使用标准的请求处理例程,就调用该函数。当请求队列上有待处理的请求时,调用rfn函数。
blk_init_queue的反操作函数为 blk_cleanup_queue ,当撤销块设备时调用后者(例如在模块卸载时)。
generic_make_request
形成块设备的I/O请求。
void generic_make_request (int rw, struct buffer_head * bh)
rw为I/O操作的类型,即READ、 WRITE或 READA,bh是内存和磁盘上的缓冲区首部。
READ和WRITE的含义很明确,READA为预读。该函数不返回任何状态。请求的成功与失败,以及操作的完成是由bh->b_end_io 递送的。
submit_bh
类似于上一个函数
void submit_bh (int rw, struct buffer_head * bh)
rw为I/O操作的类型,即READ、 WRITE或 READA,bh为描述I/O的buffer_head
该函数与与generic_make_request的目的非常类似,但submit_bh做更多的事情。
ll_rw_block
对块设备的低级访问
void ll_rw_block (int rw, int nr, struct buffer_head * * bhs)
rw为READ、 WRITE或 READA,nr为数组中buffer_heads的个数,bhs为指向buffer_heads的数组。
对普通文件的读/写和对块设备的读/写,都是通过调用该函数完成的。
所有的缓冲区必须是针对同一设备的。
内核源码学习:Linux 2.4内核API(十八)
2008-09-18 15:05
USB 设备
函数名
功能
函数形成
参数
描述
usb_register
注册一个USB设备
Int usb_register (struct usb_driver * new_driver)
new_driver为驱动程序的USB操作
注册一个具有USB核心的USB驱动程序。只要增加一个新的驱动程序,就要扫描一系列独立的接口,并允许把新的驱动程序与任何可识别的设备相关联,成功则返回0,失败则返回一个负数。
usb_scan_devices
扫描所有未申明的USB接口
Usb_scan_devices ( void)
无
扫描所有未申明的USB接口,并通过“probe”函数向它们提供所有已注册的USB驱动程序。这个函数将在usb_register()调用后自动地被调用。
usb_deregister
注销一个USB驱动程序
Usb_deregister (struct usb_driver * driver)
Driver为要注销的驱动程序的USB操作。
从USB内部的驱动程序链表中取消指定的驱动程序
usb_alloc_bus
创建一个新的USB宿主控制器结构
Struct usb_bus * usb_alloc_bus (struct usb_operations * op)
op为指向struct usb_operations的指针,这是一个总线结构
创建一个USB宿主控制器总线结构,并初始化所有必要的内部对象(仅仅由USB宿主控制器使用)。如果没有可用内存,则返回NULL。
usb_free_bus
释放由总线结构所使用的内存
Void usb_free_bus (struct usb_bus * bus)
无
(仅仅由USB宿主控制器驱动程序使用)
usb_register_bus
注册具有usb核心的USB宿主控制器
Void usb_register_bus (struct usb_bus * bus);
Bus指向要注册的总线
仅仅由USB宿主控制器驱动程序使用
内核源码学习:Linux 2.4内核API(十九)
2008-09-18 15:09
硬件接口
硬件处理
函数名
功能
函数形成
参数
描述
Disable_irq_nosync
不用等待使一个irq无效
void inline disable_irq_nosync (unsigned int irq)
irq为中断号
使所选择的中断线无效。使一个中断栈无效。与disable_ irq不同,这个函数并不确保IRQ处理程序的现有实例在退出前已经完成。可以从IRQ的上下文中调用该函数。
Disable_irq
等待完成使一个irq无效
void disable_irq (unsigned int irq)
irq为中断号
使所选择的中断线无效。使一个中断栈无效。
这个函数要等待任何挂起的处理程序在退出之前已经完成。如果你在使用这个函数,同时还持有IRQ处理程序可能需要的一个资源,那么,你就可能死锁。要小心地从IRQ的上下文中调用这个函数。
Enable_irq
启用irq的
void enable_irq (unsigned int irq)
irq为中断号
重新启用这条IRQ线上的中断处理。在IRQ的上下文中调用这个函数。
Probe_irq_mask
扫描中断线的位图
unsigned int probe_irq_mask (unsigned long val)
val为要考虑的中断掩码
扫描ISA总线的中断线,并返回活跃中断的位图。然后把中断探测的逻辑状态返回给它以前的值。
MTRR处理
Mtrr_add
增加一种内存区类型
int mtrr_add (unsigned long base, unsigned long size, unsigned int type, char
increment)
base为内存区的物理基地址,size为内存区大小,type为MTRR期望的类型,increment为布尔值,如果为真,则增加该内存区的引用计数。
内存区类型寄存器控制着较新的Intel处理器或非Intel处理器上的高速缓存。这个函数可以增加请求MTRR的驱动程序。每个处理器实现的详细资料和硬件细节都对调用者隐藏。如果不能增加内存区,则可能因为所有的区都在使用,或CPU就根本不支持,于是返回一个负数。成功则返回一个寄存器号,但应当仅仅当作一个cookie来对待。
可用的类型为:
MTRR_TYPE_UNCACHEABLE :无高速缓存
MTRR_TYPE_WRITEBACK:随时以猝发方式写回MTRR_TYPE_WRCOMB:立即写回,但允许猝发
Mtrr_del
删除一个内存区类型
int mtrr_del (int reg, unsigned long base, unsigned long size);
reg为由mtrr_add返回的寄存器,base为物理基地址,size为内存区大小。
如果提供了寄存器reg,则base和size都可忽略。这就是驱动程序如何调用寄存器。如果引用计数降到0,则释放该寄存器,该内存区退回到缺省状态。成功则返回寄存器,失败则返回一个负数。
内核源码学习:Linux 2.4内核API(二十)
2008-09-18 15:11
PCI支持库
pci_find_slot
从一个给定的PCI插槽定位PCI
struct pci_dev * pci_find_slot (unsigned int bus, unsigned int devfn)
bus为所找PCI设备所驻留的PCI总线的成员,devfn为PCI插槽的成员。
给定一个PCI总线和插槽号,所找的PCI设备位于PCI设备的系统全局链表中。如果设备被找到,则返回一个指向它的数据结构,否则返回空。
pci_find_device
根据PCI标识号开始或继续搜索一个设备
struct pci_dev * pci_find_device (unsigned int vendor, unsigned int device,
const struct pci_dev * from)
vendor为要匹配的PCI商家id,或要与所有商家id匹配的PCI_ANY_ID,device为要匹配的PCI设备id,或要与所有商家id匹配的PCI_ANY_ID,from为以前搜索中找到的PCI设备,或对于一个新的搜索来说为空。
循环搜索已知PCI设备的链表。如果找到与vendor和device匹配的PCI设备,则返回指向设备结构的指针,否则返回NULL。
给from参数传递NULL参数则开始一个新的搜索,否则,如果from不为空,则从那个点开始继续搜索。
pci_find_class
根据类别开始或继续搜索一个设备
struct pci_dev * pci_find_class (unsigned int class, const struct pci_dev *
from)
class:根据类别名称搜索PCI设备;
Previous:在搜索着找到的PCI设备,对于新的搜索则为NULL。
循环搜索已知PCI设备的链表。如果找到与 class匹配的PCI设备,则返回指向设备结构的指针,否则返回NULL。
给from参数传递NULL参数则开始一个新的搜索,否则,如果from不为空,则从那个点开始继续搜索。
pci_find_capability
查询设备的权能
int pci_find_capability (struct pci_dev * dev, int cap)
dev为要查询的PCI设备,
cap为权能取值。
断定一个设备是否支持给定PCI权能。返回在设备PCI配置空间内所请求权能结构的地址,如果设备不支持这种权能,则返回0。
pci_find_parent_resource
返回给定区父总线的资源区
struct resource * pci_find_parent_resource (const struct pci_dev * dev,
struct resource * res)
dev为设备结构,该结构包括要搜索的资源,res为要搜索的子资源记录。
对于给定设备的给定资源区,返回给定区所包含的父总线的资源区。
pci_set_power_state
设置一个设备电源管理的状态。
int pci_set_power_state (struct pci_dev * dev, int new_state)
dev为PCI设备,new_state为新的电源管理声明(0 == D0, 3 == D3等)。
设置设备的电源管理状态。对于从状态D3的转换,并不像想象的那么简单,因为很多设备在唤醒期间忘了它们的配置空间。返回原先的电源状态。
pci_save_state
保存设备在挂起之前PCI的配置空间
int pci_save_state (struct pci_dev * dev, u32 * buffer)
dev为我们正在处理的PCI设备,buffer为持有配置空间的上下文。
缓冲区必须足够大,以保持整个PCI2.2的配置空间(>= 64 bytes)。
pci_restore_state
恢复PCI设备保存的状态
int pci_restore_state (struct pci_dev * dev, u32 * buffer)
dev为我们正在处理的PCI设备,buffer为保存的配置空间。
pci_enable_device
驱动程序使用设备前进行初始化
int pci_enable_device (struct pci_dev * dev)
dev为要初始化的PCI设备。
驱动程序使用设备前对设备进行初始化。请求低级代码启用I/O和内存。如果设备被挂起,则唤醒它。小心,这个函数可能失败。
pci_disable_device
使用PCI设备之后使其无效
void pci_disable_device (struct pci_dev * dev)
dev为使无效的PCI设备
向系统发送信号,以表明系统不再使用PCI设备。这仅仅包括使PCI总线控制(如果激活)无效。
内核源码学习:Linux 2.4内核API(二十一)
2008-09-18 15:11
pci_enable_wake
当设备被挂起时启用设备产生PME#
int pci_enable_wake (struct pci_dev * dev, u32 state, int enable)
dev为对其实施操作的PCI 设备,state为设备的当前状态,enable为启用或禁用“产生”的标志。
当系统被挂起时,在设备的PM能力中设置位以产生PME#。如果设备没有PM能力,则返回-EIO。如果设备支持它,则返回-EINVAL,但不能产生唤醒事件。如果操作成功,则返回0。
pci_release_regions
释放保留的PCI I/O和内存资源
void pci_release_regions (struct pci_dev * pdev)
pdev 为PCI设备,其资源以前曾由pci_request_regions保留。
释放所有的PCI I/O和以前对pci_request_regions成功调用而使用的内存。只有在PCI区的所有使用都停止后才调用这个函数。
pci_request_regions
保留PCI I/O和内存资源
int pci_request_regions (struct pci_dev * pdev, char * res_name)
pdev为PCI设备,它的资源要被保留,res_name为与资源相关的名字。
把所有与PCI设备pdev相关联的PCI区进行标记,设备pdev是由属主res_name保留的。除非这次调用成功返回,否则不要访问PCI内的任何地址。
成功返回0,出错返回EBUSY,失败时也打印警告信息。
pci_register_driver
注册一个PCI设备
int pci_register_driver (struct pci_driver * drv)
drv为要注册的驱动程序结构。
把驱动程序结构增加到已注册驱动程序链表,返回驱动程序注册期间所声明的PCI设备号。即使返回值为0,驱动程序仍然是已注册。
pci_unregister_driver
注销一个PCI设备
void pci_unregister_driver (struct pci_driver * drv)
drv为要注销的驱动程序结构。
从已注册的PCI驱动程序链表中删除驱动程序结构,对每个驱动程序所驱动的设备,通过调用驱动程序的删除函数,给它一个清理的机会,把把这些设备标记为无驱动程序的。
pci_insert_device
插入一个热插拔设备
void pci_insert_device (struct pci_dev * dev, struct pci_bus * bus)
dev为要插入的设备,bus为PCI总线,设备就插入到该总线。
把一个新设备插入到设备列表,并向用户空间(/sbin/hotplug)发出通知。
pci_remove_device
删除一个热插拔设备
void pci_remove_device (struct pci_dev * dev)
dev为要删除的设备
把一个新设备从设备列表删除,并向用户空间(/sbin/hotplug)发出通知。
pci_dev_driver
获得一个设备的pci_driver
struct pci_driver * pci_dev_driver (const struct pci_dev * dev)
dev为要查询的设备
返回合适的pci_driver结构,如果一个设备没有注册的驱动程序,则返回NULL。
pci_set_master
为设备dev启用总线控制
void pci_set_master (struct pci_dev * dev)
dev为要启用的设备
启用设备上的总线控制,并调用pcibios_set_master对特定的体系结构进行设置。
pci_setup_device
填充一个设备的类和映射信息
int pci_setup_device (struct pci_dev * dev)
dev为要填充的设备结构
用有关设备的商家、类型、内存及IO空间地址,IRO线等初始化设备结构。在PCI子系统初始化时调用该函数。成功返回0,设备类型未知返回-1
2.4 kernel API