api crc linux
2017-05-15 23:19:53 qq_32632659 阅读数 350

1、CRC简介:

CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中常用的一种差错校验码,其特征是信息字段和校验字段的长度

可以任意选定。CRC校验实用程序库在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用检错的手段。

crc校验原理:

利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码列,以一定的规则产生一个校验用的r位监督码(CRC码),

附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,

以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。

2、生成CRC码的基本原理:

任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1

,而多项式为x5+x3+x2+x+1对应的代码101111。

3、CRC码集选择的原则:

若设码字长度为N,信息字段为K位,校验字段为R位(N=K+R),则对于CRC码集中的任一码字,存在且仅存在一个R次多项式g(x),使得
V(x)=A(x)g(x)=xRm(x)+r(x);

其中:    m(x)为K次信息多项式, r(x)为R-1次校验多项式,

         g(x)称为生成多项式:

g(x)=g0+g1x+ g2x2+...+g(R-1)x(R-1)+gRxR

发送方通过指定的g(x)产生CRC码字,接收方则通过该g(x)来验证收到的CRC码字。

标准CRC生成多项式如下表:

名称 生成多项式 简记式* 标准引用
CRC-4 x4+x+1 3 ITU G.704
CRC-8 x8+x5+x4+1 0x31
CRC-8 x8+x2+x1+1 0x07
CRC-8 x8+x6+x4+x3+x2+x1 0x5E
CRC-12 x12+x11+x3+x+1 80F
CRC-16 x16+x15+x2+1 8005 IBM SDLC
CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
CRC-32 x32+x26+x23+…+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
CRC-32c x32+x28+x27+…+x8+x6+1 1EDC6F41 SCTP

基本算法(人工笔算):
以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0];
数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。
发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];

举例:

信息字段代码为: m(x)=x6+x4+x3+1    代码为:1011001

生成多项式:    g(x)=x4+x3+1       代码为:11001

m(x)x4=x10+x8+x7+x4 对应的代码记为:10110010000     即 左移4位

m(x)x4 在与 g(x)进行 模2的除法运算,相当于按位异或,计算过程如下:

1 0 1 1 0 0 1 0 0 0 0
1 1 0 0 1
-----------------------------
0 1 1 1 1 0 1 0 0 0 0
1 1 0 0 1
-----------------------------
0 0 0 1 1 1 1 0 0 0 0
      1 1 0 0 1
-----------------------------
      0 0 1 1 1 0 0 0
          1 1 0 0 1
-----------------------------
          0 0 1 0 1 0             --------------> 余数     即 校验码





发送数据码为: 10110011010 
2015-01-10 00:02:49 linyt 阅读数 4327

Linux内核不承诺模块编程接口兼容性,事实上这类编程接口在内核主线的演进过程中,不停地发生变化。那就引出一个问题:插入模块时,内核怎么判断该模块引用的内核接口已发生变化(二进制不兼容),防止模块不经重新编译就插入内核,造成系统Oops……。


由于内核只需要检查模块调用的接口与当前内核提供的接口,在语法和语义是否完全一致(即二进制兼容);而不需要做接口的兼容,甚至保持ABI接口不变。因此不需要使用类似glibc的版本机制,或者Window下的COM方案。


内核做法相对简单,只做两件事情:

1. 判断内核版本是否一致,以及几个重要的配置选项情况是否相同(CONFIG_PREEMPT, CONFIG_SMP)

2. 判断模块引用的导出模符号的CRC值,与当前内核该符号的CRC值是否相同


只有上述两个条件满足,才能说明模块不需要重新编译,本文重点分析CRC机制。


浅谈内核模块符号CRC机制


CRC是什么,很直观的理解就是签名或者哈希,只当数据保持不变时,CRC结果才保持不变;哪怕有一丁点的变化,它都会跳出来告诉你,有变化了,接口不匹配,请重新呼叫编译器进行工作。

那么问题来了,什么情况下导出符号(EXPORT_SYMBOL)不兼容,即二进制不兼容。

其实二进制接口兼容要求保持两个不变:

1. 语法保持不变

     遵守这个条件,说明如果模块在新内核下重新编译,那应该没有任何语法问题。
     即导出符号的类型名没有变化,如果是函数,则要求参数和返回值类型没有任何变化;如果这些类型是结构体的话,结构体的成员名也没有有任何变化。

2. 语义保持不变
    
    这要求符号的类型不能有变化,如果类型本身是结构体(struct),则它成员的类型不能有变化,成员在结构体内的位置不能有变化,以及成员本身不能增删。

上述两点,背后朴素的道理就是:导出符号的签名不能有变化。

下面先讲述符号的CRC计算过程,然后再说明该CRC结果如何识别上述任何一个变化。

内核导出符号的CRC生成规则


如果你像我一样,对这个CRC生成规则感兴趣,一定要刨根问底了解它的规则才能睡着觉的话,那恭喜你,一定度过不眠之夜。因为生成这个CRC需要解释C源代码,像编译器一样,小心翼翼地根据C的语法识别各种类型定义,你得把lex和yacc的定义翻个朝天还是搞不懂。

好吧,我就以退为进吧,相信你也会赞成这个方法:增加调试输出,对感兴趣的内核符号输出CRC的整个计算过程,从而提取它的规则,然后在这里卖关子,哈哈:)

好!不扯了,下面谈一下具体的规则。

1.  CRC基本函数


Linux内核使用CRC32来做基本哈希运算, 它的定义如下:

static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
{
return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
}

具体的实现细节,可以参考内核源码。相信大家不会对这个函数感兴趣,更多是关心最终符号的CRC结果与什么正相关。

ok,为了将关注的重点转移到CRC的计算结构,我们做下面的简单定义字符串的CRC计算结果:

H(<字符串>, crc0)  := H(<子串1:未字符>, crc0) = partial_crc32_one(未字符, H(<子串1>, crc0)

这个递归定义太复杂了吧,直白地说,就是以crc0作为初值,对每个字符,都调用上述的partial_crc32_one,得到一个crc值,再将下个字符和该crc结果,调用partial_crc32_one,依次下去,直到字符串结束,得到的值就字符串的CRC值。

好了,有上述的约定,就可以计算每个符号的CRC值了。

2. 基础类型的crc规则


类型             CRC值                                             
----------------------------------------------------------------
int                H("int", 0xffffffff) ^ 0xffffffff          
char             H("char", 0xffffffff) ^ 0xffffffff       
long             H("long", 0xffffffff) ^ 0xfffffff        
....

那么再复杂一点的unsigned int, unsigned long该如何计算,很简单,使用复合+偏序的计算结构:

unsinged int的计算方法:

1) H("unsigned", 0xffffffff ) -> crc1
2) H(空白, crc1) -> crc2
3) H("int", crc2) - >crc3
4) crc3 ^ 0xfffffff -> 结果

为什么说是偏序呢?因此保持从左右到的计算结构,它的计算结构可以表示成:
0xffffffff -> "unsigned" -> 空白 -> "int" -> 0xffffffff

为了减少阅读的噪音,去掉空白、引号和0xffffffff,将这个表达结果简成下面这样:

unsigned -> int


简化之后规则,只使用计算结构进行表达,方便大家阅读。

3. 复合类型CRC规则


1. 结构体

      如 struct foo {
                   int a;
                   int b;
               };

它的crc计算方式很简单,它的计算结构为:

struct -> foo -> {  -> int -> a -> ; -> int -> b -> ; -> }

2. 数组 type arr[N];


计算结构为:
type -> arr -> [ -> N -> ]

注:这里的type本身可能是个复合类型,它的它的crc计算方法或者结构遵守上述的规则, 比如
type 为unsigned int,即:
unsigned int arr[N]

type -> arr -> [ -> N ->]  ==>unsigned int -> arr -> [ -> N -> ] ==>unsigned -> int -> arr -> [ -> N -> ]

3. 指针 type *


计算结构为: type -> *

简单的有如:int * p
它的计算结构:int -> * 

复杂的有如:
struct foo {
int a;
int b;
}

struct foo *

那么p的计算结构:
struct -> foo -> { -> int -> a -> ; -> int -> b -> ; ->} -> *


其它构造类型,在这里不一一枚举,有兴趣可以查阅相关代码;或者使有我提供的patch,对你感兴趣的类型做测试。

4. 导出变量的CRC计算方法


上在谈的一直是类型,那变量呢,因为内核导出的符号最终是变量或者函数。

假设内核有下面的导出变量

type var;
EXPORT_SYMBOL(var);

计算结构为:type -> var

5. 函数的CRC计算方法


假设内核有下面的导出函数

type1 func(type2 a, type3 b)

计算结构为:type1 -> func -> ( -> type2 -> a -> , -> type3 -> b -> )

CRC计算过程如何保持符号的语法和语义


前面提到,符号CRC值不变,意味着符号的语法和语义保持不变,下面用例子说明:

struct foo1 { 
    int a;
    int b;
};

struct foo {
         int c;
         struct foo1 b;
};

int func(int u, struct foo *foo);
EXPORT_SYMBOL(func);

那整个CRC计算结构如下:
int -> func -> (  ->
                            int -> u -> , ->
                           struct -> foo ->
                                                 { ->
                                                   int -> c -> ; ->
                                                   struct -> foo1 ->
                                                                           { ->
                                                                             int -> a -> ; ->
                                                                             int -> b -> ; ->
                                                                           } ->
                                                       b  ->
                                                   } ->
                              * -> foo ->
                        )

看到了吧:
1)语法属性:任保一个类型名,或者变量名发生变化,都会造成最终的CRC发生变化
2)语议属性:任何一个类型变化,或者结构成员出现位置调整,都会造成最终的CRC发生变化

不要恐慌


看了导出符号CRC的定义,对于通用的导出函数,只有它的类型树结构稍有点风吹草动,它的CRC就会发生变化,依赖该函数的内核模块就得重编了。

事实上没有这么大的恐慌,一般内核bugfix是不会造成核心数据结构的变化(当前是一般情况,但无绝对),因此无须太担心。 一般的bugfix只是增减代码,不会修改数据结构和函数签名。

一个具体的计算例子


上面一直使用计算结构来表过每个符号的计算过程,目的是使大家重点关注CRC值与哪些因素相关,而不是陷入万劫不复的计算细节中。 这里举个具体的例子来说明上述的计算结构是如何工作的。

数据结构的定义:
struct pair {
int a1;
int b1;
};

struct comp {
struct pair p;
long l;
};

函数定义:
void my_func_comp_p(struct comp *p) {}
EXPORT_SYMBOL(my_func_comp_p);

相信大家根据上面的规则很容易推算my_func_comp_p的计算结构。下面调试日志记录的计算过程,crc可以理解成上面的H定义。

上面描述计算结构时,我们一直将空格(空白字符)没有写出来,实际在计算过程,是需要使用空白字符来计算的。否则CRC就无法区分"unsigned int"类型和"unsignedint"变量了。

crc(void, 0xffffffff) = 0x2d842611
crc( , 0x2d842611) = 0x51f3841c
crc(my_func_comp_p, 0x51f3841c) = 0x3cde0c75
crc( , 0x3cde0c75) = 0x1b3d7b77
crc((, 0x1b3d7b77) = 0xfbcf711e
crc( , 0xfbcf711e) = 0xc19ad2da
crc(struct, 0xc19ad2da) = 0x0950984a
crc( , 0x0950984a) = 0xad6ed8de
crc(comp, 0xad6ed8de) = 0xfc468378
crc( , 0xfc468378) = 0x654c9f45
crc({, 0x654c9f45) = 0xc1045134
crc( , 0xc1045134) = 0x1a1bd02c
crc(pair, 0xffffffff) = 0xf6a5e196
crc(struct, 0x1a1bd02c) = 0x64623aa1
crc( , 0x64623aa1) = 0x9adbd18c
crc(pair, 0x9adbd18c) = 0x71ccf17f
crc( , 0x71ccf17f) = 0xfba58094
crc({, 0xfba58094) = 0x304e5a69
crc( , 0x304e5a69) = 0x0f30b76e
crc(int, 0x0f30b76e) = 0x2404ed55
crc( , 0x2404ed55) = 0x204b815e
crc(a1, 0x204b815e) = 0x93bfb9fb
crc( , 0x93bfb9fb) = 0x1192b4e5
crc(;, 0x1192b4e5) = 0x617a6d67
crc( , 0x617a6d67) = 0xe8d9ae5e
crc(int, 0xe8d9ae5e) = 0x42b9fbe6
crc( , 0x42b9fbe6) = 0x7245de7e
crc(b1, 0x7245de7e) = 0xd6c2d0f1
crc( , 0xd6c2d0f1) = 0xf1022092
crc(;, 0xf1022092) = 0xaffb196c
crc( , 0xaffb196c) = 0x7fc5f6a2
crc(}, 0x7fc5f6a2) = 0x16130ab3
crc( , 0x16130ab3) = 0x6910d1f4
crc(p, 0x6910d1f4) = 0xeabc57e8
crc( , 0xeabc57e8) = 0x9555f6d5
crc(;, 0x9555f6d5) = 0x47279a89
crc( , 0x47279a89) = 0xaf4d3cd6
crc(long, 0xaf4d3cd6) = 0x372303f4
crc( , 0x372303f4) = 0x818935ce
crc(l, 0x818935ce) = 0x38594bf1
crc( , 0x38594bf1) = 0xf1ecbb09
crc(;, 0xf1ecbb09) = 0xc826bd3b
crc( , 0xc826bd3b) = 0x8aadef51
crc(}, 0x8aadef51) = 0x3252c10c
crc( , 0x3252c10c) = 0x32ea3e22
crc(*, 0x32ea3e22) = 0x0ee9620c
crc( , 0x0ee9620c) = 0x32d68581
crc(), 0x32d68581) = 0xd83ffd5f
crc( , 0xd83ffd5f) = 0xc0625350
0xc0625350 ^ 0xffffffff = 0x3f9dacaf
Result:  my_func_comp_p = 0x3f9dacaf

为什么会有这篇文章


相信大家都带着一个很大的疑问看到这里,为什么需要知道符号CRC的计算规则;将模块插入到内核时,只有符号CRC值有变化,内核会报告模块插入失败,重编模块就是了,对系统造成影响。

事实上,我是个苦逼的程序员,每次在内核合入小的修改,都尽可能地减少CRC的变化;如果有变化,还需要告诉为什么会有变化。这需求很贴心吧。

另外一点,这个CRC机制是否可以应用于 程序跟动态库的接口兼容 检查,开发一个新工具来检测修改前和修改后编译出来的动态库,对外接口上是否完全二进制兼容,这也是我们所期望的。

有需要请联系


csdn博客不能上传代码,可谓一大遗憾。我通过修改生成crc模块的代码,增加调试信息,可以在编译过程中,通过命令行参数来控制,生成哪些导出符号CRC 的详细计算过程,有兴趣的小伴伙请联系我。
Locations of visitors to this page
linux API
2012-12-03 11:28:35 uyiwfn 阅读数 519
stat函数讲解

表头文件:    #include <sys/stat.h>
             #include <unistd.h>
定义函数:    int stat(const char *file_name, struct stat *buf);
函数说明:    通过文件名filename获取文件信息,并保存在buf所指的结构体stat中
返回值:      执行成功则返回0,失败返回-1,错误代码存于errno

错误代码:
    ENOENT         参数file_name指定的文件不存在
    ENOTDIR        路径中的目录存在但却非真正的目录
    ELOOP          欲打开的文件有过多符号连接问题,上限为16符号连接
    EFAULT         参数buf为无效指针,指向无法存在的内存空间
    EACCESS        存取文件时被拒绝
    ENOMEM         核心内存不足
    ENAMETOOLONG   参数file_name的路径名称太长


#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    struct stat buf;
    stat("/etc/hosts", &buf);
    printf("/etc/hosts file size = %d\n", buf.st_size);
}


-----------------------------------------------------
struct stat {
    dev_t         st_dev;       //文件的设备编号
    ino_t         st_ino;       //节点
    mode_t        st_mode;      //文件的类型和存取的权限
    nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
    uid_t         st_uid;       //用户ID
    gid_t         st_gid;       //组ID
    dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
    off_t         st_size;      //文件字节数(文件大小)
    unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
    unsigned long st_blocks;    //块数
    time_t        st_atime;     //最后一次访问时间
    time_t        st_mtime;     //最后一次修改时间
    time_t        st_ctime;     //最后一次改变时间(指属性)
};

先前所描述的st_mode 则定义了下列数种情况:
    S_IFMT   0170000    文件类型的位遮罩
    S_IFSOCK 0140000    scoket
    S_IFLNK 0120000     符号连接
    S_IFREG 0100000     一般文件
    S_IFBLK 0060000     区块装置
    S_IFDIR 0040000     目录
    S_IFCHR 0020000     字符装置
    S_IFIFO 0010000     先进先出

    S_ISUID 04000     文件的(set user-id on execution)位
    S_ISGID 02000     文件的(set group-id on execution)位
    S_ISVTX 01000     文件的sticky位

    S_IRUSR(S_IREAD) 00400     文件所有者具可读取权限
    S_IWUSR(S_IWRITE)00200     文件所有者具可写入权限
    S_IXUSR(S_IEXEC) 00100     文件所有者具可执行权限

    S_IRGRP 00040             用户组具可读取权限
    S_IWGRP 00020             用户组具可写入权限
    S_IXGRP 00010             用户组具可执行权限

    S_IROTH 00004             其他用户具可读取权限
    S_IWOTH 00002             其他用户具可写入权限
    S_IXOTH 00001             其他用户具可执行权限

    上述的文件类型在POSIX中定义了检查这些类型的宏定义:
    S_ISLNK (st_mode)    判断是否为符号连接
    S_ISREG (st_mode)    是否为一般文件
    S_ISDIR (st_mode)    是否为目录
    S_ISCHR (st_mode)    是否为字符装置文件
    S_ISBLK (s3e)        是否为先进先出
    S_ISSOCK (st_mode)   是否为socket


    若一目录具有sticky位(S_ISVTX),则表示在此目录下的文件只能被该文件所有者、此目录所有者或root来删除或改名。

-----------------------------------------------------
struct statfs {
    long    f_type;          //文件系统类型
    long    f_bsize;         //块大小
    long    f_blocks;        //块多少
    long    f_bfree;         //空闲的块
    long    f_bavail;        //可用块
    long    f_files;         //总文件节点
    long    f_ffree;         //空闲文件节点
    fsid_t f_fsid;           //文件系统id
    long    f_namelen;       //文件名的最大长度
    long    f_spare[6];      //spare for later
};

stat、fstat和lstat函数(UNIX)


#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。感觉一般是文件没有打开的时候这样操作。
int fstat(int filedes, struct stat *buf);
通过文件描述符获取文件对应的属性。文件打开后这样操作
int lstat(const char *restrict pathname, struct stat *restrict buf);
连接文件

三个函数的返回:若成功则为0,若出错则为-1
给定一个pathname,stat函数返回一个与此命名文件有关的信息结构,fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。

第二个参数是个指针,它指向一个我们应提供的结构。这些函数填写由buf指向的结构。该结构的实际定义可能随实现而有所不同,但其基本形式是:

struct stat{
mode_t st_mode;   /*file tpye &mode (permissions)*/
ino_t st_ino;     /*i=node number (serial number)*/
dev_t st_rdev;   /*device number for special files*/
nlink_t st_nlink; /*number of links*/
uid_t    st_uid; /*user id of owner*/
gid_t    st_gid; /*group ID of owner*/
off_t   st_size; /*size in bytes for regular files*/
time_t st_atime; /*time of last access*/
time_t st_mtime; /*time of last modification*/
time_t st_ctime; /*time of last file status change*/
long st_blksize; /*best I/O block size */
long st_blocks; /*number of 512-byte blocks allocated*/
};
   注意,除最后两个以外,其他各成员都为基本系统数据类型。我们将说明此结构的每个成员以了解文件属性。
 
使用stat函数最多的可能是ls-l命令,用其可以获得有关一个文件的所有信息。
1 函数都是获取文件(普通文件,目录,管道,socket,字符,块()的属性。
函数原型
#include <sys/stat.h>

int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。
int fstat(int filedes, struct stat *buf);
通过文件描述符获取文件对应的属性。
int lstat(const char *restrict pathname, struct stat *restrict buf);
连接文件描述命,获取文件属性。
2 文件对应的属性
struct stat {
        mode_t     st_mode;       //文件对应的模式,文件,目录等
        ino_t      st_ino;       //inode节点号
        dev_t      st_dev;        //设备号码
        dev_t      st_rdev;       //特殊设备号码
        nlink_t    st_nlink;      //文件的连接数
        uid_t      st_uid;        //文件所有者
        gid_t      st_gid;        //文件所有者对应的组
        off_t      st_size;       //普通文件,对应的文件字节数
        time_t     st_atime;      //文件最后被访问的时间
        time_t     st_mtime;      //文件内容最后被修改的时间
        time_t     st_ctime;      //文件状态改变时间
        blksize_t st_blksize;    //文件内容对应的块大小
        blkcnt_t   st_blocks;     //伟建内容对应的块数量
      };
linux api
2014-01-13 16:57:40 WMJ75617718 阅读数 568

flockfile


 void flockfile(FILE *filehandle);


进程内线程的互斥, 针对文件指针,同一文件的不同的文件指针对应不同的锁,不会互相影响
fp1 = fopen("xx", "w+");
fp2 = fopen("xx", "w+");
// 下面俩个均可锁上
flockfile(fp1); 
flockfile(fp2);

fcntl


fcntl(fd, F_SETLK, &lock);

进程间互斥锁,针对的是具体的文件对象,可以对文件内某个具体区域上锁,同一进程内,不论文件描述符(通过open,dup等获得新的fd)是否相同,只要它们指的是同一文件,便是指的同一个锁
fd1 = open("xx", ...); 
fcntl(fd1,F_SETLK, ...);  // 
fd2 = open("xx", ...);
// 同一进程内的后来的锁总是会生效
fcntl(fd1, F_SETLK, ...);  // 生效
fcntl(fd1, F_SETLK, ...);  // 生效
fcntl(fd2, F_UNLK, ...); // fd1上的锁也被释放


flock

int flock(int fd, int operation);

进程间互斥锁,针对的是文件描述符;同一文件不同文件描述符对应相同的锁,锁住整个文件
同一进程内,被锁住后,后面再锁会失败
flock不提供锁检查,也就是说在用flock之前需要用户自己去检查一下是否已经上了锁,说明白点就是读写文件之前用一下flock检查一下文件有没有上锁
A  call  to  flock() may block if an incompatible lock is held by another process
 Locks created by flock() are associated with an open file table entry.  This means that duplicate file  descriptors  (cre?
       ated  by,  for  example, fork(2) or dup(2)) refer to the same lock, and this lock may be modified or released using any of
       these descriptors.  Furthermore, the lock is released either by an explicit LOCK_UN operation on any  of  these  duplicate
       descriptors, or when all such descriptors have been closed.




       If a process uses open(2) (or similar) to obtain more than one descriptor for the same file, these descriptors are treated
       independently by flock().  An attempt to lock the file using one of these file descriptors may be denied by  a  lock  that
       the calling process has already placed via another descriptor.


2009-08-30 09:55:00 android83 阅读数 708
    The Linux Kernel API is an application programming interface providing a uniform method for device drivers and other low-level software written for the Linux kernel to access system resources and services.

linux c CRC,异或校验,累加和源码

阅读数 3329

#include"chijiu.h"staticunsignedcharhbyte[]={0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1, 0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1, 0x81,0x40,0x0,

博文 来自: wujxping

linux用户api和内核api

阅读数 1

1:系统调用:系统调用是值操作系统提供给用户程序调用的一组“特殊”编程接口,用户程序可以通过这组“特殊”接口获得操作系统内核提供的服务。例如,用户可以通过进程控制相关的系统调用来创建进程,实现进程调度,进程管理等!Linux中,为了更好地保护内核空间,将程序运行空间分为内核空间和用户空间(也就是常说的内核态和用户态),它们分别运行在不同的级别上,逻辑上相互隔离的。因此,用户进...

博文 来自: weixin_34311757

linux hook api

阅读数 450

编译hook库    gcc-shared源文件名-o共享库文件名-ldl-fPIC    如果共享库中用到了dlopen则需要-ldl  设置环境变量 LD_PRELOAD如    LD_PRELOAD="./libmyc.so"

博文 来自: swimablefish

linux 工作队列之API

阅读数 444

自2.6.20起,工作队列的数据结构发生了一些变化,使用时不能沿用旧的方法。1、在工作队列中被调用的函数原形如下:   typedefvoid(*work_func_t)(structwork_struct*work);2、定义了一个新的结构delayed_work用于处理延迟执行:structdelayed_work{   structw

博文 来自: peijian1998

The Linux Kernel API

阅读数 6

http://www.gnugeneration.com/books/linux/2.6.20/kernel-api/index.htmlNameplatform_get_resource—getaresourceforadeviceSynopsisstructresource*platform_get_resource(structplatf...

博文 来自: weixin_34124651
没有更多推荐了,返回首页