华为技术有限公司C语言编程基础课件_第1页
华为技术有限公司C语言编程基础课件_第2页
华为技术有限公司C语言编程基础课件_第3页
华为技术有限公司C语言编程基础课件_第4页
华为技术有限公司C语言编程基础课件_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、华为技术有限公司C语言编程基础内部公开目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美前言提高我司产品竞争力,研发要在以下几个方面下功夫:提高规划水平,把握正确的方向(战略)提高设计水平,搭建合理的系统(战术)提高编码水平,开发稳定的代码(单兵作战技能)前言我们为什么要进行培训?最好的医术是预防真正的难问题往往是低级错误引起的我们的编码水平不容乐观C是程序员的语言前言要提高编码水平,每个开发人员要做到:勤学苦练,提高编程技能前车之鉴,后世之师,不犯同样的错误;坚持代码Review、PC-LINT检查和单元测试;总

2、而言之,就是少犯错误,尽早发现错误目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之简单就是美If (a & b | c | d = e & f)这个表达式的正确运算顺序是什么?test(a+, +a, a+, +a, a+, +a)a = 1;实际函数调用时,传入的参数值分别是多少?(+*p+) (-*q-)语义是什么?a= b=1,c=2,d=3; e=4;a的值是多少?基础篇之简单就是美这里没有答案,只有问题:我们问什么要写这样的代码?工作太轻松?BUG不够多?水平显不出?如何改进?优先级搞不清楚用括

3、号;复合语句太罗嗦,拆成几行来写;套用两句广告词:把简单的事情复杂化,太累把复杂的事情简单化,贡献!基础篇之简单就是美编码的三不原则不要挑战自己的记性不要挑战同事的耐心不要挑战编译器的水平编码的三用原则能用简单语句的,就不要用复杂的技巧能用成熟代码的,就不要再来一套能用上工具的,就一定要机械化我们要求什么?struct XXXchar cA;short sB;long lC;void main()char *pChar;pChar = (char *)malloc(7);memcpy(pChar, abcdefgh, sizeof(XXX);printf(%sn, pChar); return

4、;我们要求什么?续struct XXXchar cA;short sB;long lC;void main()char *pChar;pChar = (char *)malloc(7); /*0,魔鬼数字; 1,未申请成功怎么办?*/memcpy(pChar, “abcdefgh”, sizeof(XXX); /*2,内存越界*/printf(“%sn”, pChar); /*3,没有字符串结束符*/ return; /*4,没有释放内存*/目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之sizeof数据

5、结构是C语言的基础C语言的灵活性很大程度上在于其数据结构的灵活性要用好数据结构,首先要掌握数据结构大小的计算系统为每个数据结构、每个变量都会分配一个对应的存储空间,这个存储空间的大小就是数据结构的尺寸基础篇之sizeoftypedef union record LONG lIndex; SHORT sLevel6; CHAR cPos; REC_S;REC_SstMax,*pMax;CHARstr = “Hello” ;CHAR*pChar = str ;ULONGulGrade = 10;USHORTusClass 10;DOUBLEdWeightUCHAR*pCharArray1010;S

6、izeof(stMax/pMax/str/pChar/ulGrade/usClass/dWeight/pCharArray)的取值分别是多少?基础篇之sizeoftypedef union record LONG lIndex; SHORT sLevel6; CHAR cPos; REC_S;REC_SstMax(12),*pMax(4);CHARstr = “Hello”(516,不要忘了0) ;CHAR*pChar = str (4);ULONGulGrade = 10(4);USHORTusClass 10(2);DOUBLEdWeight(8);UCHAR*pCharArray1010

7、(41010400);目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之字节对齐随着半导体技术的发展,我们经历8bit、16bit、32bit乃至64bit的CPU,我们产品当前大多使用32bit CPU从内存存取效率来说,4字节对齐的存取速度是最快的,非对齐情况下,CPU需要分解成两次32bit操作;缺省情况下,编译器自动对数据结构进行四字节对齐,以提高程序执行的效率,在特殊情况下,可以通过预编译指定指定数据结构为1字节对齐或者其他;对于Power PC/Intel系列CPU,在非四字节对齐情况下,由CP

8、U自动完成两次操作,对上层应用透明;对于MIPS CPU,则需要通过编译选项进行干预,或者调整数据结果避免出现这种情况,否则会产生例外;字节对齐对数据结构的尺寸(sizeof)直接产生影响基础篇之字节对齐typedef struct Head CHAR src 6; ULONG ulType; HEAD_S;VOID Encapsulation(CHAR* pBuf) ULONG ulLen, ulDestIP; CHAR* pData = pBuf; ulLen = sizeof(HEAD_S); pData += ulLen; ulDestIP = VOS_NTOHL(IP_S *)pDa

9、ta-ulDestIP); return;基础篇之字节对齐#pragma pack(push)#pragma pack(1)typedef struct Head CHAR src 6; ULONG ulType; HEAD_S;#pragma pack(pop)VOID Encapsulation(CHAR* pBuf) ULONG ulLen, ulDestIP; CHAR* pData = pBuf; ulLen = sizeof(HEAD_S); pData += len; ulDestIP = VOS_NTOHL(IP_S *)pData-ulDestIP); (MIPS CPU 异

10、常) return;基础篇之字节对齐数据结构内部对齐,下面2种定义哪个好?typedef struct example USHORT usA; ULONG ulA; USHORT usB; UCHAR ucA; USHORT usC; EXAMPLE_SVStypedef struct example ULONG ulA; USHORT usA; USHORT usB; USHORT usC; UCHAR ucA; UCHAR ucReserved; EXAMPLE_S 基础篇之字节对齐案例点评在定义数据结构时(尤其是涉及协议和IPC通讯的时候),没有特殊理由的话,都定义成四字节对齐;这样做可

11、能浪费几个字节,但是不会出问题;除了数据结构总长度是四字节对齐外,每一个部分也要保证它是四字节对齐的(可以按照四字节、两字节、一字节的顺序排放数据结构中的各个域);对于无法定义成四字节对齐的数据结构,如以太网II、HDLC等,则将它们强行定义成一字节对齐,以规避这个问题;对于MIPS CPU,在必须面对非四字节对齐情况时,采用编译选项方式加以解决;目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之字节序X86系统:VOID QosConfigPolicy() ulDestIP = 从命令行读取用户配置的参数

12、; pQosPolicy-ulDestIP = ulDestIP; return;主机处理:VOID QosClassify() pIp = (IP_S *)pData; if (pIp-ulDestIp = pQosPolicy-ulDestIP) DoSomething(); return ;基础篇之字节序X86系统:VOID QosConfigPolicy() ulDestIP = 从命令行读取用户配置的参数; pQosPolicy-ulDestIP = ulDestIP; return;主机处理:VOID QosClassify() pIp = (IP_S *)pData; if (V

13、OS_HTONL(pQosPolicy-ulDestIP) = pIp-ulDestIp ) DoSomething(); return ;基础篇之字节序由于历史的原因,业界存在两种字节序标准:BigEndian和LittleEndian,Power PC是大头,X86是小头,有些CPU可以通过寄存器设置支持不同的字节序,例如MIPS;所谓大头就是高位在低字节,低位在高字节;小头则与此相反,以0 x345678为例,大头内存从低到高的存放次序为00,34,56,78,小头内存从低到高的存放次序为78,56,34,00;(上面的数值统一为16进制表示形式)字节序问题广泛存在于设备与设备之间、单板

14、与单板之间、单板与底层芯片之间,只要两个处理单元的字节序不同,这个问题就存在,为了解决不同字节序的处理单元之间的通信问题,业界定义了主机序和网络序的概念,网络序主要用于信息传递,一般不用于计算,其字节顺序与大头一致;除了在编码时绷紧这根弦以外,我们在器件选择时尽量选择主机序与网络序一致的芯片,同一设备的不同单板使用相同的字节序,并优先选择支持大头的芯片,这样,即使不能彻底解决问题,也可以彻底规避问题。目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之函数参数在C语言中,函数通过返回值和参数与调用者交换信息,

15、对参数理解和使用的正确与否,直接影响到函数功能能否正确实现;函数参数自身占用的存储单元在堆栈中分配,入口参数指向的数值或者地址在函数入口处拷贝到堆栈区中,因此对函数参数所在存储单元的直接修改不会作用到函数之外,而对参数存储单元中存放的地址指向的存储空间的修改,则会在函数之外其作用;调用者在进行函数调用之前,必须事先申明被调用函数的原型,包括返回值类型和参数类型;基础篇之函数参数BOOL GetMemory(CHAR *p) /* 申请内存 */ p = (CHAR *)malloc(100); if (NULL = p) return FALSE; else return TRUE; VOID

16、 Test(void) CHAR *str = NULL; If (GetMemory(str) strcpy(str, hello world); printf(str); return;基础篇之函数参数CHAR* GetMemory(CHAR *p) /* 申请内存 */ *p = (CHAR *)malloc(100); return *p;VOID Test(void) CHAR *str = NULL; If (NULL != GetMemory(&str) strcpy(str, hello world); printf(str); free(str); str = NULL; r

17、eturn;目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之返回值在C语言中,函数的调用者通过返回值了解函数的执行情况;函数缺省的返回值类型为int,编程规范要求必须显示定义函数的返回类型;对于反映了函数执行状态的返回值,调用者必须依据返回值进行相应的处理,尤其是对于函数执行异常的情形;函数的出口参数能够起到与返回值类似的作用,上面一条规则对出口参数同样适用;对于函数返回值为恒值的函数,建议使用VOID类型的返回值;基础篇之返回值有什么问题?#includestdlib.h“VOID main() CHA

18、R *p; p=(CHAR *)malloc(100); VOS_Strcpy(p, “Hello World!n”); printf(p); free(p); return;基础篇之返回值#includestdlib.h“VOID main() CHAR *p; p=(CHAR *)malloc(100); if (NULL != p) strcpy(p, “Hello World!n”); printf(p); free(p); return;基础篇之返回值LONG A() if (条件1) return; return VOS_OK;VOID B() if (A() DoSomeThin

19、g1(); else DoSomeThing2(); return;基础篇之返回值LONG A() if (条件1) return VOS_ERROR; return VOS_OK;VOID B() if (A() DoSomeThing1(); else DoSomeThing2(); return;目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之强制类型转换强制类型转换给C语言编程带来了极大的灵活性,也正是这种灵活性,也埋下了无数的隐患;当目的结构的空间大于源结构的空间时,要重点关注内存访问超过源结构

20、范围的情形,可能越界;当目的结构的空间小于源结构的空间时,要重点关注对目的结构赋值不能完全覆盖源结构范围的情形,可能遗漏;与结构体之间的强制类型转换相比,基本数据结构的强制类型转换更容易出现上面描述的情况,使用的时候,一定要慎之又慎;基础篇之类型转换目的结构小于源结构VOID B(CHAR *p) *p =1; return;VOID A() ULONG a; B(CHAR *)(&a); return;a = ? ,是1吗?基础篇之类型转换目的结构小于源结构VOID B(CHAR *p) *p =1; return;VOID A() ULONG a; B(CHAR *)(&a); retur

21、n;a = ? ,是1吗?不可预知。基础篇之类型转换目的结构大于源结构VOID B(ULONG *p) *p =1000; return;VOID A() UCHAR a 10; B(ULONG *)(&a); return;在函数B给*p赋值之前,*p的值是多少?*p赋值之后,会出现什么样的情形?基础篇之类型转换目的结构大于源结构VOID B(ULONG *p) *p =1000; return;VOID A() UCHAR a 10; B(ULONG *)(&a); return;在函数B给*p赋值之前,*p的值是多少?不可预知*p赋值之后,会出现什么样的情形?越界目录前言sizeof字节

22、对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之switchcaseC语言使用switchcase处理一个条件的多个取值有不同的处理分支的情形;当所有的case都匹配不成功时,进入default分支,编程规范要求switchcase必须显示设置default分支,如果程序从逻辑上不可能走到这个分支,可以在该分支中使用断言;结束case分支的执行最常用的办法是使用break/return,否则程序将自动进入下一个case分支继续执行;编译器对switchcase可以做优化,用空间换取时间;default分支按照编程规范,要求放在s

23、witch case的末尾,C语言本身不做强制要求;基础篇之switchcaseVOID main( ) LONG ulCnt1=0,ulCnt2=0; CHAR* ch = “aha!” ; while (*ch) switch (*ch ) case a: case h: ulCnt2+; default: ulCnt1+; ch+; printf(%u,%un,ulCnt1,ulCnt2); return; ulCnt1和ulCnt2分别是多少?基础篇之switchcaseVOID main( ) LONG ulCnt1=0,ulCnt2=0; CHAR* ch = “aha!” ; w

24、hile (*ch) switch (*ch ) case a: case h: ulCnt2+; default: ulCnt1+; ch+; printf(%u,%un,ulCnt1,ulCnt2); return; ulCnt14 ulCnt2=3目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之字符串ULONG BuildRun(CHAR* ppBuildrun) ULONG ulLen; CHAR* pBuf; ulLen = CalculateBuildRunLen(); if (0 = ulL

25、en) *ppBuildrun = NULL; return B_ZERO_LENGTH; pBuf = VOS_malloc(0, ulLen); if (NULL = pBuf) *ppBuildrun = NULL; return B_MALLOC_FAILED; VOS_StrCpy(pBuf, BuildRunInfo); *ppBuildrun = pBuf; return VOS_OK; 基础篇之字符串ULONG BuildRun(CHAR* ppBuildrun) ULONG ulLen; CHAR* pBuf; ulLen = CalculateBuildRunLen();

26、if (0 = ulLen) *ppBuildrun = NULL; return B_ZERO_LENGTH; pBuf = VOS_malloc(0, ulLen + 1); if (NULL = pBuf) *ppBuildrun = NULL; return B_MALLOC_FAILED; VOS_StrCpy(pBuf, BuildRunInfo); *ppBuildrun = pBuf; return VOS_OK; 基础篇之字符串案例点评:作为信息输出,字符串必不可少;字符串在动态申请时少分配一个字符是非常普遍的一个错误;strlen等计算字符串长度的函数都是不考虑字符串的0结

27、束符的;代码Review时,字符串越界问题是一个大客户,要盯紧看严;基础篇之字符串(续)再看一个例子:LONG GetXYZHead(CHAR* pData, CHAR* pBuf) ULONG ulLen; CHAR* pTmpData = *pData, *pTmpBuf = *pBuf; ulLen = AnalysisHead(pTmpBuf); /* strcpy(pTmpData, pTmpBuf); */ /* sprintf(pTmpData, “%s”, pTmpBuf); */ /* memcpy(pTmpData,pTmpBuf, ulLen); */ return ul

28、Len;*pBuf中存放是是XYZ协议的Peer发送过来的一段报文,这个函数负责将协议头拷贝到pData指向的空间中;假设空间是足够的,打算选择哪条语句;基础篇之字符串(续)LONG GetXYZHead(CHAR* pData, CHAR* pBuf) ULONG ulLen; CHAR* pTmpData = *pData, *pTmpBuf = *pBuf; ulLen = AnalysisHead(pTmpBuf); /* strcpy(pTmpData, pTmpBuf); */ /* sprintf(pTmpData, “%s”, pTmpBuf); */ memcpy(pTmpD

29、ata,pTmpBuf, ulLen); return ulLen;使用memcpy,因为没有人保证协议头中不出现0,而且协议头非常容易出现这个值,这个时候它就不再是字符串,字符串工具函数必须是专款专用,而memcpy则要宽泛得多;基础篇之字符串(再续)VOID GetDigitString(CHAR* pData, CHAR* pBuf) CHAR *pTmpData = pData, *pTmpBuf = pBuf; while (0 != (*pTmpBuf) if (0 = *pTmpBuf) *pTmpData = *pTmpBuf; pTmpData+; else break; p

30、TmpBuf+; return;该函数的功能是将pBuf中的连续数字拷贝到pData中生成一个新的字符串基础篇之字符串(再续)VOID GetDigitString(CHAR* pData, CHAR* pBuf) CHAR *pTmpData = pData, *pTmpBuf = pBuf; while (0 != (*pTmpBuf) if (0 = *pTmpBuf) *pTmpData = *pTmpBuf; pTmpData+; else break; pTmpBuf+; *pTmpData = 0; /* 没有尾字符,就不是字符串 */ return;目录前言sizeof字节对齐

31、字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之溢出#define DEFAULT_EXPIRE_TIME 300000 /* 5分钟 */VOID ARPRecordExpireTime(ARP_Entry_S *pArpEntry) /* 计算表项预计老化时的时间,以系统启动以来的毫秒数表示 */ pARPEntry-ulExpireTime = GetBootTime()+DEFAULT_EXPIRE_TIME; return;VOID* ARPExpire( ARP_Entry_S *pArpEntry) ARP_Entry

32、_s* pArpNext; while(pArpEntry) if (GetBootTime() ulExpireTime) break; pArpNext = pArpEntry-pNext; Free(pArpEntry); pArpEntry = pArpNext; return (VOID *)pArpEntry;基础篇之溢出#define DEFAULT_EXPIRE_TIME 300000 /* 5分钟 */VOID ARPRecordExpireTime(ARP_Entry_S *pArpEntry) /* 计算表项预计老化时的时间,以系统启动以来的毫秒数表示 */ pARPEn

33、try-ulExpireTime = GetBootTime()+ DEFAULT_EXPIRE_TIME; return;VOID* ARPExpire( ARP_Entry_S *pArpEntry) ARP_Entry_s* pArpNext; while(pArpEntry) if (GetBootTime() ulExpireTime) /* ULONG溢出如何处理?包括ExpireTime溢出、GetBootTime溢出*/ /* 解决方案作为思考题 */ break; pArpNext = pArpEntry-pNext; Free(pArpEntry); pArpEntry =

34、 pArpNext; return (VOID *)pArpEntry;基础篇之溢出案例点评:在我们的系统中,溢出通常出现在时间处理上;系统时钟一般使用两个ULONG表示时间,精确到毫秒;上层软件使用时间时一般忽略掉高位,只保留低32位。对于LONG的情况,25天后翻转;对于ULONG的情况,49天后翻转;如果没有特殊的需要,建议使用系统提供的精确到秒的32位时钟,在LONG情况下60年翻转,基本可以不考虑这件事情;如果一定要使用毫秒钟,就需要考虑时钟翻转的情况;基础篇之溢出(续)ULONG SequenceAdd(ULONG ulCount) ULONG ulSum = 0; while (

35、0 = ulCount ) ulSum += ulCount; ulCount-; return ulSum;基础篇之溢出(续)ULONG SequenceAdd(ULONG ulCount) ULONG ulSum = 0; while (0 pBody = pBody; pNode-ulNType = ulNType; return pNode;基础篇之资源释放(续)Node_Head_S* CreateNode(ULONG ulNType) Node_Head_S *pNode; Node_Body_S *pBody; pNode = (Node_Head_S *)malloc(size

36、of(Node_Head_S); if (NULL = pNode) return NULL; pBody = (Node_Body_S *)malloc(sizeof(Node_Body_S); if (NULL = pBody) Free(pNode); /* 异常分支最容易忘记打扫战场,顾头也要顾尾 */ return NULL; pNode-pBody = pBody; pNode-ulNType = ulNType; return pNode;基础篇之资源释放案例点评资源泄漏是代码Review中最常见的错误之一申请的每个资源必须明确由谁负责释放,何时释放,在何处释放;在异常分支中,保

37、持清醒的头脑,清理战场;在特定功能去使能时,需要完成的主要工作就是资源清退;目录前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之if规范LONG IsZero(ULONG ulCnt) if (ulCnt = 0) return W_ZERO; else return W_NONZERO; 函数的功能为:参数为0时返回W_ZERO;否则返回W_NOZERO;基础篇之if规范LONG IsZero(ULONG ulCnt) if (0 = ulCnt) return W_ZERO; else return W_

38、NONZERO; 编程规范反复强调变量放在双等号的右边,常量放在左边,就是为了规避出现If (ulCnt = 0)这种语法正确,但是极有可能是笔误的情况。为了杜绝这种不必要的逻辑问题,要求必须严格遵守编程规范。基础篇之if规范(续)If (ulCnt = ulData)VsulCnt = ulData;If (ulCnt)VsIf (ulCnt = ulData)上面的语句语法上都是正确的,但写法哪个好?基础篇之if规范(续)If (ulCnt = ulData)VsulCnt = ulData;If (ulCnt)VsIf (ulCnt = ulData)第一种和第三种非常容易出现笔误,为了

39、杜绝不必要的问题,不要使用第一种方式编写程序,而用方式二替代;基础篇之if规范(再续)VOID Test() if (Func_A() & Func_B() DoSomething_A(); else DoSomething_B(); return;在任何情况下是否语义都是正确的?基础篇之if规范(再续)VOID Test() VOID Test() ULONG ulRet1, ulRet2; if (Func_A() ulRet1 = Func_A(); ulRet2 = Func_B(); if (Func_B() if (ulRet1 & ulRet2) DoSomething_A();

40、 DoSomething_A(); else else DoSomething_B(); DoSomething_B(); return; else DoSomething_B(); return; 如果程序逻辑为Func_A的返回值为假的情况下,不执行Func_B,则上一页的程序是正确的,但是要求采用本页右侧的程序模式实现;如果Func_A和Func_B都无条件执行,再根据综合结果,决定走哪个分支,则使用本页左侧的程序;为了明确程序逻辑,同时要求使用注释加以说明,以方便后期的维护基础篇之if规范(续三)VOS_Assert(Func_A()vsVOS_DBGASSERT(Func_A()这两

41、个用法有什么区别?VOS_Aseert()用法保证在任何情况下Func_A都得到执行;VOS_DBGASSERT则与系统是打开release宏还是debug宏相关:当系统打开了debug宏时,起语义与方式1完全相同;当系统打开的是release宏,则VOS_DBGASSERT在编译时将被忽略,Func_A自然页得不到运行;使用VOS_DBGASSERT的时候要谨慎,要清楚了解不同系统宏下的不同语义,要保证两种场景下,程序逻辑都是正确的;为了避免不必要的麻烦,要求不允许在VOS_DBGASSERT中使用函数!基础篇之if规范(续四)LONG IsA (CHAR ch) if ( a != ch)

42、 | ( A != ch) return VOS_ERROR; else return VOS_OK; 函数功能为判断输入的字符是否是a或者A,如果是,则返回VOS_OK,否则返回VOS_ERROR基础篇之if规范(续四)LONG IsA (CHAR ch) if ( a != ch) | ( A != ch) /* 逻辑恒为真,逻辑错误,笔误? */ return VOS_ERROR; else return VOS_OK; PC-LINT可以检查出逻辑恒为真或者假的逻辑表达式,基本都是我们预期之外的逻辑,PC-LINT确实是一个好东西。目录前言sizeof字节对齐字节序函数参数返回值强制类

43、型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美基础篇之临界资源保护VOID SendMBuf(MBUF_S *pMBuf) 空闲BD数 = DRV_GetFreeBD(); 报文片数 = MBUF_GetFrag(pMBuf); if (报文片数 空闲BD数) return; /* 发送拥塞,暂时缓存 */ intr_lock(); CopyMBufIntoBD(); 空闲BD数 -= 报文片数; intr_unlock();Task SOCK: Intr:SendMBuf(pMBuf);SendMBuf(pMBuf);基础篇之临界资源保护VOID SendMBuf(MBUF_S *pMBuf) intr_lock(); /* 彻底保护 */ 空闲BD数 = DRV_GetFreeBD(); 报文片数 = MBUF_GetFrag(pMBuf); if (报文片数 空闲BD数) intr_unlock()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论