一些常用的函数 宏

来源:互联网 发布:包车软件哪个好 编辑:程序博客网 时间:2024/05/21 11:12

<!--@page { margin: 2cm }P { margin-bottom: 0cm }P.western { font-size: 10pt }P.cjk { font-size: 10pt }H1 { margin-bottom: 0.21cm }H1.western { font-family: "Arial", sans-serif; font-size: 16pt }H1.cjk { font-family: "文鼎PL简中楷"; font-size: 16pt }H1.ctl { font-family: "文鼎PL简中楷"; font-size: 16pt }-->

内核相关:kthread_createkthread_runkthread_stopAsmlinkageHZtick and jiffieBUG()BUG_ON()shmat

c相关:<!--@page { margin: 2cm }P { margin-bottom: 0cm }P.western { font-size: 10pt }P.cjk { font-size: 10pt }H1 { margin-bottom: 0.21cm }H1.western { font-family: "Arial", sans-serif; font-size: 16pt }H1.cjk { font-family: "文鼎PL简中楷"; font-size: 16pt }H1.ctl { font-family: "文鼎PL简中楷"; font-size: 16pt }TD P { margin-bottom: 0cm }A:link { so-language: zxx }--> memchrstrncmpsscanfSprintfisspace

<!--@page { margin: 2cm }P { margin-bottom: 0cm }P.western { font-size: 10pt }P.cjk { font-size: 10pt }H1 { margin-bottom: 0.21cm }H1.western { font-family: "Arial", sans-serif; font-size: 16pt }H1.cjk { font-family: "文鼎PL简中楷"; font-size: 16pt }H1.ctl { font-family: "文鼎PL简中楷"; font-size: 16pt }-->

kthread_create

使用kthread_create创建线程:
structtask_struct *kthread_create(int (*threadfn)(void *data),

void*data,
const char *namefmt, ...);
这个函数可以像printk一样传入某种格式的线程名
线程创建后,不会马上运行,而是需要将kthread_create()返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。

kthread_run

当然,还有一个创建并启动线程的函数:kthread_run
struct task_struct *kthread_run(int (*threadfn)(void *data),
void*data,
const char *namefmt, ...);

kthread_stop

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。
int kthread_stop(structtask_struct *thread);
kthread_stop()
通过发送信号给线程。
如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。

在执行kthread_stop的时候,目标线程必须没有退出,否则会Oops。原因很容易理解,当目标线程退出的时候,其对应的task结构也变得无效,kthread_stop引用该无效task结构就会出错。

 

Asmlinkage

看一下/usr/include/asm/linkage.h里面的定义:
#defineasmlinkage CPP_ASMLINKAGE__attribute__((regparm(0)))
__attribute__
是关键字,是gccC语言扩展,regparm(0)表示不从寄存器传递参数

如果是__attribute__((regparm(3))),那么调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数。

如:asmlinkagelong sys_sync(void);

 

HZ, tick and jiffie

linux核心每隔固定遧期會發出timerinterrupt (irq 0)hz是用來定義每一秒有幾次timerinterrupts

tickhz的倒數,意即timerinterrupt每發生一次中斷的時間。如hz250時,tick4毫秒(millisecond)

jiffieslinux核心變數(unsignedlong),它被用來紀錄系統自開幾以來,已經過多少的tick

BUG()BUG_ON()

作用:一些内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()BUG_ON()。当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。为什么这些声明会导致oops跟硬件的体系结构是相关的。大部分体系结构把BUG()BUG_ON()定义成某种非法操作,这样自然会产生需要的oops。你可以把这些调用当作断言使用,想要断言某种情况不该发生:
if(bad_thing)
BUG();
或者使用更好的形式:
BUG_ON(bad_thing);

可以用panic()引发更严重的错误。调用panic()不但会打印错误消息而且还会挂起整个系统。显然,你只应该在极端恶劣的情况下使用它:
if(terrible_thing)
panic("foo is %ld/n", foo);

有些时候,你只是需要在终端上打印一下栈的回溯信息来帮助你测试。此时可以使用dump_stack()。它只在终端上打印寄存器上下文和函数的跟踪线索:
if(!debug_check) {
printk(KERN_DEBUG "provide someinformation.../n");
dump_stack();
}
from:http://www.lupaworld.com/bbs/thread-36983-1-8.html

 

Alots of places in linux kernel we encounter the macro BUG_ON.
BUG_ONmacro first checks for the condition and if condition is true then itcalls BUG which do a printk of msg and call panic which halts thesystem.(
如果BUG_ON中的条件为真就调用BUG,它输出一些信息,然后调用panic函数挂起系统。)

Theunlikely in BUG_ON macro is compiler directive whichask compiler to generate assembly such that the condition mentionedin unlikely isn't going to be met most-of-the time , which reducesjumps and speeds-up things, although if condition mentioned inunlikely met then there will be a long jump and speed will beeffected, so must be used carefully. Same is with likely as it is theopposite of unlikely .(据说likely一般是很少用的)

 

shmat

作用:共享内存区对象映射到调用进程的地址空间

  核心处理函数:void*shmat( int shmid , char *shmaddr , int shmflag);shmat()是用来允许本进程访问一块共享内存的函数。

  intshmid是那块共享内存的ID

  char*shmaddr是共享内存的起始地址

  intshmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式

  成功时,这个函数返回共享内存的起始地址。失败时返回-1

  最近用到内存共享,收集整理了些资料,做了个简单的对比

memchr

原型:externvoid *memchr(void *buf, char ch, unsigned count);

  头文件:#include<string.h>

  功能:从buf所指内存区域的前count个字节查找字符ch

  说明:当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL

strncmp

原型:externint strcmp(char *s1,char * s2intn);

头文件:#include<string.h>

功能:比较字符串s1s2的前n个字符。

说明:

s1<s2时,返回值<0

s1=s2时,返回值=0

s1>s2时,返回值>0

sscanf

函数原型:

  Int sscanf(const char *, const char *, ...);

  int scanf(const char *, ...);

  头文件:#include<stdio.h>

  1.常见用法。

  charbuf[512] = ;

  sscanf("123456", "%s", buf);//此处buf是数组名,它的意思是将123465%s的形式存入buf中!

返回值:有多少个变量被赋值。intn= sscanf(str,"%2d%2d",&x,&y);

Sprintf

函数原型:

#include<stdio.h>

intsprintf(char *string, char *farmat [,argument,...]);

详细描述:函数sprintf()的用法和printf()函数一样,只是sprintf的作用是将一个格式化的字符串输出到一个目的字符串中,而printf是将一个格式化的字符串输出到屏幕。

  例如: sprintf(s,"%d", 123); //把整数123打印成一个字符串保存在s中。

返回值:返回本次函数调用打印到字符缓冲区中的字符数目

isspace

  #include<ctype.h>

  定义函数

  intisspace(int c)

  函数说明:检查参数c是否为空格字符,也就是判断是否为空格('')、定位字符('/t')CR('/r')、换行('/n')、垂直定位字符('/v')或翻页('/f')的情况。

  返回值 :若参数c为空格字符,则返回TRUE,否则返回NULL(0)

  附加说明: 此为宏定义,非真正函数。

 

基本C库函数

当编写驱动程序时,一般情况下不能使用C标准库的函数。Linux内核也提供了与标准库函数功能相同的一些函数,但二者还是稍有差别。

类别

函数名

功能

函数形成

参数

描述

字符串转换

simple_strtol

把一个字符串转换为一个有符号长整数

longsimple_strtol (const char * cp, char ** endp, unsigned int base)

cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。

 

simple_strtoll

把一个字符串转换为一个有符号长长整数

long longsimple_strtoll (const char * cp, char ** endp, unsigned int base)

cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。

 

simple_strtoul

把一个字符串转换为一个无符号长整数

long longsimple_strtoul (const char * cp, char ** endp, unsigned int base)

cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。

 

simple_strtoull

把一个字符串转换为一个无符号长长整数

long longsimple_strtoull (const char * cp, char ** endp, unsigned int base)

cp指向字符串的开始,endp为指向要分析的字符串末尾处的位置,base为要用的基数。

 

vsnprintf

格式化一个字符串,并把它放在缓存中。

intvsnprintf (char * buf, size_t size, const char * fmt, va_listargs)

buf为存放结果的缓冲区,size为缓冲区的大小,fmt为要使用的格式化字符串,args为格式化字符串的参数。

 

snprintf

格式化一个字符串,并把它放在缓存中。

intsnprintf (char * buf, size_t size, const char * fmt, ... ...)

buf为存放结果的缓冲区,size为缓冲区的大小,fmt为格式化字符串,使用@…来对格式化字符串进行格式化,…为可变参数。

 

vsprintf

格式化一个字符串,并把它放在缓存中。

intvsprintf (char * buf, const char * fmt, va_list args)

buf为存放结果的缓冲区,size为缓冲区的大小,fmt为要使用的格式化字符串,args为格式化字符串的参数。

 

sprintf

格式化一个字符串,并把它放在缓存中。

int sprintf(char * buf, const char * fmt, ... ...)

buf为存放结果的缓冲区,size为缓冲区的大小,fmt为格式化字符串,使用@…来对格式化字符串进行格式化,…为可变参数。

 

字符串操作

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_tstrlen (const char * s)

s为给定的字符串

 

strnlen

给出给定长度字符串的长度

size_tstrnlen (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_toiomemcpy_fromio

memcpy

把内存的一个区域拷贝到另一个区域

void *memcpy (void * dest, const void * src, size_t count)

dest为目的字符串,Src为源字符串,而count为内存区的大小

I/O空间的访问应当用memcpy_toiomemcpy_fromio

memmove

把内存的一个区域拷贝到另一个区域

void *memmove (void * dest, const void * src, size_t count)

dest为目的字符串,Src为源字符串,而count为内存区的大小

memcpymemmove处理重叠的区域,而该函数不处理。

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,则返回空。

位操作

set_bit

在位图中原子地设置某一位

voidset_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

在位图中清某一位

voidclear_bit (int nr, volatile void * addr)

nr为要清的位,addr为位图的起始地址

该函数是原子操作,但不具有加锁功能,如果要用于加锁目的,应当调用smp_mb__before_clear_bitsmp_mb__after_clear_bit函数,以确保任何改变在其他的处理器上是可见的。

__change_bit

在位图中改变某一位

void__change_bit (int nr, volatile void * addr)

nr为要设置的位,addr为位图的起始地址。

change_bit不同,该函数是非原子操作。

change_bit

在位图中改变某一位

voidchange_bit (int nr, volatile void * addr)

nr为要设置的位,addr为位图的起始地址。

 

test_and_set_bit

设置某一位并返回该位原来的值

inttest_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

清某一位,并返回原来的值

inttest_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

改变某一位并返回该位的新值

inttest_and_change_bit (int nr, volatile void * addr)

nr为要设置的位,addr为位图的起始地址。

该函数为原子操作

test_bit

确定某位是否被设置

inttest_bit (int nr, const volatile void * addr)

nr为要测试的第几位,addr为位图的起始地址。

 

 find_first_zero_bit

在内存区中查找第一个值为0的位

intfind_first_zero_bit (void * addr, unsigned size)

addr为内存区的起始地址,size为要查找的最大长度

返回第一个位为0的位号

find_next_zero_bit

在内存区中查找第一个值为0的位

intfind_next_zero_bit (void * addr, int size, int offset)

addr为内存区的起始地址,size为要查找的最大长度,offset开始搜索的起始位号。

 

ffz

在字中查找第一个0

unsignedlong ffz (unsigned long word);

word为要搜索的字。

 

ffs

查找第一个已设置的位

int ffs(int x)

x为要搜索的字。

这个函数的定义方式与Libc中的一样。

hweight32

返回一个N位字的加权平衡值

hweight32 (x)

x为要加权的字

一个数的加权平衡是这个数所有位的总和。

 


 

kthread_create

使用kthread_create创建线程:
structtask_struct *kthread_create(int (*threadfn)(void *data),

void*data,
const char *namefmt, ...);
这个函数可以像printk一样传入某种格式的线程名
线程创建后,不会马上运行,而是需要将kthread_create()返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。

kthread_run

当然,还有一个创建并启动线程的函数:kthread_run
struct task_struct *kthread_run(int (*threadfn)(void *data),
void*data,
const char *namefmt, ...);

kthread_stop

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。
int kthread_stop(structtask_struct *thread);
kthread_stop()
通过发送信号给线程。
如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。

在执行kthread_stop的时候,目标线程必须没有退出,否则会Oops。原因很容易理解,当目标线程退出的时候,其对应的task结构也变得无效,kthread_stop引用该无效task结构就会出错。

 

Asmlinkage

看一下/usr/include/asm/linkage.h里面的定义:
#defineasmlinkage CPP_ASMLINKAGE__attribute__((regparm(0)))
__attribute__
是关键字,是gccC语言扩展,regparm(0)表示不从寄存器传递参数

如果是__attribute__((regparm(3))),那么调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数。

如:asmlinkagelong sys_sync(void);

 

HZ, tick and jiffie

linux核心每隔固定遧期會發出timerinterrupt (irq 0)hz是用來定義每一秒有幾次timerinterrupts

tickhz的倒數,意即timerinterrupt每發生一次中斷的時間。如hz250時,tick4毫秒(millisecond)

jiffieslinux核心變數(unsignedlong),它被用來紀錄系統自開幾以來,已經過多少的tick

BUG()BUG_ON()

作用:一些内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()BUG_ON()。当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。为什么这些声明会导致oops跟硬件的体系结构是相关的。大部分体系结构把BUG()BUG_ON()定义成某种非法操作,这样自然会产生需要的oops。你可以把这些调用当作断言使用,想要断言某种情况不该发生:
if(bad_thing)
BUG();
或者使用更好的形式:
BUG_ON(bad_thing);

可以用panic()引发更严重的错误。调用panic()不但会打印错误消息而且还会挂起整个系统。显然,你只应该在极端恶劣的情况下使用它:
if(terrible_thing)
panic("foo is %ld/n", foo);

有些时候,你只是需要在终端上打印一下栈的回溯信息来帮助你测试。此时可以使用dump_stack()。它只在终端上打印寄存器上下文和函数的跟踪线索:
if(!debug_check) {
printk(KERN_DEBUG "provide someinformation.../n");
dump_stack();
}
from:http://www.lupaworld.com/bbs/thread-36983-1-8.html

 

Alots of places in linux kernel we encounter the macro BUG_ON.
BUG_ONmacro first checks for the condition and if condition is true then itcalls BUG which do a printk of msg and call panic which halts thesystem.(
如果BUG_ON中的条件为真就调用BUG,它输出一些信息,然后调用panic函数挂起系统。)

Theunlikely in BUG_ON macro is compiler directive whichask compiler to generate assembly such that the condition mentionedin unlikely isn't going to be met most-of-the time , which reducesjumps and speeds-up things, although if condition mentioned inunlikely met then there will be a long jump and speed will beeffected, so must be used carefully. Same is with likely as it is theopposite of unlikely .(据说likely一般是很少用的)

 

shmat

作用:共享内存区对象映射到调用进程的地址空间

  核心处理函数:void*shmat( int shmid , char *shmaddr , int shmflag);shmat()是用来允许本进程访问一块共享内存的函数。

  intshmid是那块共享内存的ID

  char*shmaddr是共享内存的起始地址

  intshmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式

  成功时,这个函数返回共享内存的起始地址。失败时返回-1

  最近用到内存共享,收集整理了些资料,做了个简单的对比

原创粉丝点击