![第16章-嵌入式Linux-C语言标准库课件_第1页](http://file4.renrendoc.com/view/c06f8025b1fc4ff54e340e6a79acb92d/c06f8025b1fc4ff54e340e6a79acb92d1.gif)
![第16章-嵌入式Linux-C语言标准库课件_第2页](http://file4.renrendoc.com/view/c06f8025b1fc4ff54e340e6a79acb92d/c06f8025b1fc4ff54e340e6a79acb92d2.gif)
![第16章-嵌入式Linux-C语言标准库课件_第3页](http://file4.renrendoc.com/view/c06f8025b1fc4ff54e340e6a79acb92d/c06f8025b1fc4ff54e340e6a79acb92d3.gif)
![第16章-嵌入式Linux-C语言标准库课件_第4页](http://file4.renrendoc.com/view/c06f8025b1fc4ff54e340e6a79acb92d/c06f8025b1fc4ff54e340e6a79acb92d4.gif)
![第16章-嵌入式Linux-C语言标准库课件_第5页](http://file4.renrendoc.com/view/c06f8025b1fc4ff54e340e6a79acb92d/c06f8025b1fc4ff54e340e6a79acb92d5.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第16章嵌入式LinuxC语言标准库虽然C语言的功能非常强大,但它事实上是一种非常精练的语言,C的简单性和兼容性使得它的应用非常广泛,大到巨型机的操作系统,小至电子表,都可以很好的运行。在不同的环境中,C的运行方式可能有所差异。在独立运行(如在电子表等设备中)的条件下只能实现语言本身所提供的功能,一些如输入输出、内存管理、字符操作等常见功能并没有包含在这种运行方式中。而在非独立运行的条件下,可以通过调用库提供的函数,实现C所没有提供的功能。在众多的库当中,使用频率最高的当属C标准库,以至于很多的程序员认为标准库是语言的一部分,一些几乎在每个程序中都会出现的函数,如printf、scanf等,其实都是由标准库提供的函数,而不是语言本身的特性。16.1Glibc简介Glibc(GNUCLibrary)是GNU发布的C标准库,也即C的运行库,是Linux系统中最底层的应用程序开发接口(API),几乎其他的库都会依赖与Glibc。在Glibc中不仅封装了操作系统提供的各种系统服务,而且也提供了许多其他一些必要功能的实现。16.2字符测试和数据转换函数16.2.1字符测试函数<ctype.h>中的函数支持单个字符的典型操作,例如确定一个字符a是否为小写,在很多C语言的教科书中都采用了如下的表达式:(‘a’<c=&&c<=’z’)这样写的程序可读性很差,而且这种方式只在ASCII字符集中有效,在别的字符集中结果是未知的。16.2.2数据转换函数这类函数的主要功能是完成将字符或字符串转换为不同类型的数,主要定义在头文件<stdlib.h>中。16.3基本I/O函数Linux针对输入输出(I/O)的函数很直观,可以总结为四个方面:打开、读取、写入和关闭,对应的有四个系统调用,它们是:open()、read()、write()、close()。16.3.1open()函数新的文件描述符是从open()函数得到的。首先回顾该函数的原型:intopen(constchar*pathname,intflags,mode_tmode);它的三个参数的含义如下:参数pathname: 为C字符串,表示打开的文件名;参数intflags: 为一个或多个标志,部分可用的标志请读者参见表16-5;参数mode_tmode:产生文件的权限模式,可以使用八进制数来表示新文件的权限,也可采用<sys/stat.h>中定义的符号常量,如表16-6所示。当打开已有文件时,将忽略这个参数。16.3.2close()函数当使用完文件可以使用close()关闭该文件,close()会让缓冲区中的数据写回磁盘,并释放该文件所占用的资源。该函数的原型如下:intclose(intfd);参数fd为文件描述符,由open()等函数所返回的有效的文件描述符。若文件顺利关闭则返回0,发生错误则返回-1,并置errno。通常文件在关闭时出错是不常见的,但也不是不可能的情况,特别是关闭通过网络访问的文件来说就会出现这种情况。16.3.3read()函数和write()函数输入输出的操作最终是通过read()和write()这两个函数来完成的,它们的形式和使用方法十分相近,因而放在一起介绍。它们的函数原型为:ssize_tread(intfd,void*buf,size_tcount);ssize_rwrite(intfd,constvoid*buf,size_tcount);这两个函数的参数都有:参数fd,表示已打开文件的文件描述符;参数buf,为指向缓冲区的指针;参数count,为要读取或写入的字节数。16.3.4其他函数其他常用的基本I/O函数还有表16-7所列的这些。16.4标准I/O函数基于文件流的标准I/O函数与前面所提的基本I/O函数最大的区别就是对缓冲区的利用。低级I/O函数在很多应用中是不带缓冲区的,程序员可以直接操作硬件,这样为开发驱动等底层的系统应用提供了方便。而在高层次的应用中,不带缓冲区的I/O操作效率往往较低,而由用户自行维护缓冲区不仅繁琐,而且容易出错。因此ANSI制定了一系列基于流缓冲的标准I/O函数,如fopen()、printf()、scanf()等。16.4.1fopen()函数打开文件有三个标准函数,分别为:fopen(),fdopen()和freopen()。它们的函数原型如下所示:#include<stdio.h>FILE*fopen(constchar*path,constchar*mode);FILE*fdopen(intfd,constchar*mode);FILE*freopen(constchar*path,constchar*mode,FILE*stream);它们以不同的模式打开文件,并返回一个指向文件流的FILE指针,此后对文件读写都是通过这个FILE指针来进行。16.4.2fclose()函数关闭文件指针的函数为fclose,它的函数原型是:intfclose(FILE*stream);这时缓冲区的数据将写入文件中,并释放系统所提供的文件资源。如果只是希望将缓冲区中的数据写入文件,但因为可能后面还要用到文件指针,不希望这个时候关闭它,可以使用另外一个函数:fflush(),函数原型如下:intfflush(FILE*stream);16.4.3fread()和fwrite()函数当利用fopen()函数打开文件后,就可对文件流进行读写操作了。根据每次读写的数据量的不同,可分为块读写、字符读写和字符串读写三类函数,其中后两类函数主要是针对文本文件的。下面主要介绍针对块读写的fread()和fwrite()函数。fread()函数和fwrite()函数的原型是:size_tfread(void*ptr,size_tsize,size_tnmemb,FILE*stream);size_tfwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream);16.4.4printf()和scanf()函数相信所有知道C语言的读者都十分熟悉这两个函数,在著名的HelloWorld程序中就有printf()函数。这类函数称为格式化输入输出函数,可以指定输入输出的具体格式,而不像前面所介绍的fread()和fwrite()函数只能读写原始的数据。标准库针对不同的实际应用提供了一些print()函数和scanf()函数的变体,如下所列的这些:intprintf(constchar*format,…)intfprintf(FILE*fp,constchar*format,…)intsprintf(char*buf,constchar*format,…)intscanf(constchar*format,…)intfscanf(FILE*fp,constchar*format,…)intsscanf(char*buf,constchar*format,…)16.4.5其他函数在实际应用中,标准I/O函数是比较常用的,笔者在表16-11中简要列出了一些函数的原型和功能,读者在需要用到时,可通过man手册查询这些函数的详细用法。16.5内存配置及字符串处理函数内存的使用是程序设计中需要仔细考虑的重要因素。特别是在嵌入式系统中,内存资源是十分宝贵的,内存管理的好坏直接影响到最终程序的执行效率及稳定性。动态内存的使用可以总结为三个步骤:(1)申请:告诉系统需要多大的内存空间,系统准备好一整块内存空间后,将这段内存的首地址返回给调用者;(2)使用:对内存空间中的数据进行复制、比较、检索、清除等工作;(3)释放:告诉系统不再需要这段内存空间,系统将其回收。本节将按照这三个步骤介绍标准库中提供的内存配置函数。其中字符串处理函数的实质也是对内存进行操作,因此在下面一并作介绍。16.5.1内存分配函数程序可以使用malloc()函数和calloc()函数来动态分配内存,函数原型是:#include<stdlib.h>void*malloc(size_tsize);void*calloc(size_tnmemb,size_tsize);16.5.2memXXX函数常见的内存操作主要有复制、查找、清除和设置,标准库提供了几个函数为操作任意的内存块提供了底层服务。1.内存设置函数:memset()memset()函数将参数val的值复制到buf的前count个字节中去。在前面的例程中,我们就用到这个函数清除内存块,下面的代码总结了这样的清除过程:void*p=malloc(sizeof(char)*count);if(p!=NULL)memset(p,0,count*sizeof(char));2.内存复制函数:memcpy()、memmove()、memccpy()memcpy()函数从src处复制count字节的数据到dest,但是他不处理内存区域的重叠问题。memmove()函数与memcpy函数类似,也是从src处复制count字节的数据到dest。但是它处理重叠内存区域问题。memcpy()函数从src处复制count字节的数据到dest,但当遇到以下情况中的一种是即停止复制:数据中包含val,则将val复制到dest后,就停止复制;数据中不包含val,则复制完count字节的数据之后,就停止复制。3.内存块比较函数memcmp()memcmp()函数比较任意类型的两个数据缓冲区中的count个字节的内容,如果buf1小于、等于或大于buf2,将分别返回负数、零或正数,如下面的例程所示4.搜索字节值函数:memchr()memchr()函数从缓冲区头开始搜寻buf所指的内存空间的前count个字节,知道发现第一个值为val的字节,返回指向该值在缓冲区中的位置的指针,如果没有找到则返回0。16.5.3strXXX函数16.5.4释放内存的函数动态分配的内存在使用完毕后一定要及时的释放,完成这个操作的函数是free()。这个函数唯一的参数是一个指针:#include<stdlib.h>voidfree(void*ptr);16.5.5动态内存分配的实例下面是一个实现单向链表插入、查找和遍历方法的例子,其中实现插入操作的函数是Insert()、实现获取操作的函数是get(),通过顺序遍历链表查找或获取某个节点。16.6日期时间函数在Shell中,我们可以通过date命令获得系统的日期和时间,而在程序中,我们往往需要有更为精确的时间表示,如计算程序的执行时间就需要得到秒级甚至毫妙级的计时信息。本节将讨论Linux系统中表示时间的方法,以及如何在程序中获得时间和计算时间。16.6.1时间的定义同现实世界一样,在Linux系统中也存在若干关于时间和日期的定义,不同的时间函数基于不同的时间定义,要用好这些函数有必要先了解相关的背景知识。这里我为读者列举了一些常见的定义,它们是:UTC(CoordinatedUniversalTime):协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(GreenwichMeanTime,GMT)。CalendarTime:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。epoch:时间点,即UTC的1970年1月1日00:00:00。linux中系统时间中采用的是从epoch开始计算的时间,其系统调用time()函数得到的就是从epoch到当前时刻的秒计数;clocktick:时钟计时单元(有的资料中称做时钟滴答次数),一个时钟计时单元的时间长短是由CPU控制的。16.6.2日历时间标准库的<time.h>头文件中定义了时间和日期的结构和方法,其中最重要的数据类型是time_t类型,用time_t表示的时间(日历时间)是从epoch时间点到此时的秒数。在<time.h>中,我们可以看到time_t是一个长整型数:typedeflongtime_t;/*时间值*/16.6.3时钟计时单元如果要计算某个算法的执行时间,使用日历时间显然是不够精确的,因为它只能精确到秒级。获得更高精度的时间则要使用clock()函数,该函数原型如下:#include<time.h>clock_tclock(void);16.6.4格式化日期和时间structtm中的成员包含了所有的时间信息,程序员完全可以亲自编写代码,按自己需要的格式输出日期和时间。但标准库提供了功能强大的格式化函数,可以满足大多数情况下的显示需求,减轻了程序员的工作量。可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,下面是两个函数的原型:#include<time.h>char*asctime(conststructtm*timeptr);char*ctime(consttime_t*timer);16.6.5自定义时间格式函数strftime()可以将时间格式化为我们想要的格式。它的原型如下:size_tstrftime(char*strDest,size_tmaxsize,constchar*format,conststructtm*timeptr);该函数类似与sprintf()函数,它的参数介绍如下:参数strDest:保存已格式化的字符串的缓冲区;参数maxsize:缓冲区的大小;参数format:格式化字符串;参数timeptr:指向structtm的指针,表示将要被格式化的时间。16.7其他函数16.7.1错误处理函数良好的程序不仅应该确保程序的正确执行,而且当程序出现错误时能有效的提供出错信息,便于用户查询。C语言本身缺乏异常和错误处理机制,标准C库为一个运行中的进程提供了一个预定义的变量,称为errno。在前面的几节中我们可以发现标准库函数在报告错误时基本都采用了两种方法:函数返回错误代码或成功代码,如果是错误代码,则代码本身可用于指出何处出错;函数返回特定值(或值范围)以指明错误,且设置全局变量errno以指明问题可能的原因。1.perror()函数perror()函数用来将上一个函数发生错误的原因输出到标准错误(STDERR)。该函数的声明如下:#include<stdio.h>voidperror(constchar*s);2.strerror()函数strerror()只返回错误代码所对应的描述字符串指针,不直接输出。它的函数声明如下:#include<stdio.h>char*strerror(interrnum);16.7.2系统日志函数Linux下提供日志服务的程序叫syslogd,它的任务就是记录各种由其他程序发给它的消息。在文
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度书画艺术品市场代理销售合同
- 2025年度建筑安全风险评估与监测委托合同
- 2025年度国际知识产权转让合同样本
- 2024-2025学年福建省福州第十中学高一上学期期中考试历史试卷
- 2025年公共租赁场地安全协议
- 2025年合作协议订立与实施年
- 2025年医院护师职责合同
- 2025年农场土地租赁合同年协议书
- 2025年TBBS项目申请报告模稿
- 2025年焦化二甲苯项目规划申请报告模范
- 酒店长包房租赁协议书范本
- 2 找春天 公开课一等奖创新教学设计
- 2025年江苏护理职业学院高职单招语文2018-2024历年参考题库频考点含答案解析
- 2025年江苏南京水务集团有限公司招聘笔试参考题库含答案解析
- 【道法】开学第一课 课件-2024-2025学年统编版道德与法治七年级下册
- 口腔门诊分诊流程
- 建筑工程施工安全管理课件
- 2025年春新外研版(三起)英语三年级下册课件 Unit2第1课时Startup
- 2025年上半年毕节市威宁自治县事业单位招考考试(443名)易考易错模拟试题(共500题)试卷后附参考答案
- 处方点评知识培训
- 2025年新合同管理工作计划
评论
0/150
提交评论