嵌入式Linux操作系统第2章-2

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

嵌入式Linux操作系统第2章Linux编程基础Linux下的C语言编程1VIM编辑器2GCC编译器3GDB调试器4Make工程管理器5第2章Linux编程基础Linux下的集成开发环境6文件I/O编程7进程控制编程8进程间的通信和同步9多线程编程10Linux下的集成开发环境集成开发环境是将一些开发工具集合到同一个操作界面的工具软件,它通常由项目管理器、文件管理器、文本编辑工具、语法纠正器、编译工具、调试工具组成。在Linux系统中开发C、C++语言程序,可选择的集成开发环境有Eclipse和Kdevelop,分别运行在GNOME桌面环境和KDE桌面环境。Linux系统下的集成开发环境通常自身不包含编译器和调试器,而是直接利用GCC、GDB等工具进行组合。工具组合正代表了Linux系统上软件设计的思想。Linux下的集成开发环境Kdevelop是一个支持多种程序设计语言的集成开发环境,它运行在KDE桌面环境,可支持C、C++语言程序发开。Kdevelop很好的支持了Qt图形界面工具包,因此是开发KDE桌面工具的理想环境。用于开发C、C++语言程序时,它的主要特性如下:源代码高亮显示,Kdevelop的编译功能和调试功能该编辑器支持源代码高亮显示和自动缩进的功能.。项目管理,项目管理器可以管理各种不同的项目类型,。类浏览器,该功能可在进行面向对象开发时,快速了解对象的结构。GUI设计器,可进行可见即可得的方式编辑软件的图形界面。并行版本控制,支持CVS、Subversion、Perforce和ClearCase等常用版本控制工具。Linux下的集成开发环境Eclipse最初是由IBM公司开发,2001年11月正式贡献给开源社区,现在由非营利软件供应商联盟Eclipse基金会管理。2003年,OSGi服务平台规范成为Eclipse运行时架构。最初Eclipse用于开发Java语言程序,但加入CDT插件后就能进行C和C++语言程序开发,并具备如下特性:显示提纲,Outline窗口模块可显示源代码中的过程、变量、声明以及函数的位置。源代码辅助,可结合上下文提示需要输入的源代码,并检查源代码中的语法错误。源代码模板,扩展源代码辅助功能中使用的源代码标准,加入自定义的源代码段,可加快代码编辑速度。源代码历史记录,在没有使用CVS等版本控制工具的情况下,也可记录源代码的修改情况。Linux下的集成开发环境Eclipse运行需要JRE支持,所以首先要确保系统中已安装JRE。Eclipse首次运行要求配置工作目录workspace,这个目录是默认用来存放源代码与相关项目文件的位置,当前用户必须有该目录读写和执行的权限。Linux下的集成开发环境Eclipse界面由数个视图窗格组成。左边是ProjectExplorer视图,该视图用于创建、选择和删除项目。正中是编辑器区域,该区域用于编辑源代码,可同时打开多个文件。右侧是Outline视图,在编辑器中显示文档的大纲,这个大纲的内容取决于源文件的类型。对于C和C++源代码文件,该大纲将显示所有被包含的函数库、函数、常量、变量、已声明的类、属性和方法等信息。Linux下的集成开发环境编译与运行源代码前,首先需要保证GCC、G++编译器和GDB调试器已安装。Eclipse通过调用GCC、G++编译器实现源代码编译,因此必须要将源代码的相关信息建立为项目文件,这样才能使Eclipse知道该使用哪一个编译指令。Linux下的集成开发环境Eclipse的Debug功能是调用GDB调试器实现的,与GDB的命令行不同,Eclipse提供了更友好的图形界面查看调试信息。要在代码中加入断点,可直接在文本编辑区右击左侧区域弹出的菜单中操作。然后单击Run|Debug命令菜单,进入Debug界面。文件I/O编程所谓系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。例如用户可以通过进程控制相关的系统调用来创建进程、实现进程调度、进程管理等。为什么用户程序不能直接访问系统内核提供的服务呢?这是由于在Linux中,为了更好地保护内核空间,将程序的运行空间分为内核空间和用户空间(也就是常称的内核态和用户态),它们分别运行在不同的级别上,在逻辑上是相互隔离的。因此,用户进程在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。但是,在有些情况下,用户空间的进程需要获得一定的系统服务(调用内核空间程序),这时操作系统就必须利用系统提供给用户的“特殊接口”——系统调用规定用户进程进入内核空间的具体位置。进行系统调用时,程序运行空间需要从用户空间进入内核空间,处理完后再返回到用户空间。文件I/O编程前面讲到的系统调用并不是直接与程序员进行交互的,它仅仅是一个通过软中断机制向内核提交请求,以获取内核服务的接口。在实际使用中程序员调用的通常是用户编程接口——API系统命令相对API更高了一层,它实际上一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能。内核空间用户空间用户编程接口API应用程序(系统命令,其他应用程序)系统调用文件I/O编程内核如何区分和引用特定的文件呢?这里用到一个重要的概念—文件描述符。对于Linux而言,所有对设备和文件的操作都是使用文件描述符来进行的。文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符;当需要读写文件时,也需要把文件描述符作为参数传递给相应的函数。通常,一个进程启动时,都会打开3个文件:标准输入、标准输出和标准出错处理。文件描述符宏标准输入0STDIN_FILENO标准输出1STDOUT_FILENO标准出错2STDERR_FILENO文件I/O编程open()函数是用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。所需头文件:#includesys/types.h#includesys/stat.h#includefcntl.h原型:intopen(constchar*pathname,intflags,intperms)文件I/O编程open函数语法要点文件I/O编程close()函数是用于关闭一个被打开的文件。当一个进程终止时,所有被它打开的文件都由内核自动关闭,很多程序都使用这一功能而不显示地关闭一个文件。文件I/O编程read()函数是用于将从指定的文件描述符中读出的数据放到缓存区中,并返回实际读入的字节数。若返回0,则表示没有数据可读,即已达到文件尾。读操作从文件的当前指针位置开始。当从终端设备文件中读出数据时,通常一次最多读一行。文件I/O编程write()函数是用于向打开的文件写数据,写操作从文件的当前指针位置开始。对磁盘文件进行写操作,若磁盘已满或超出该文件的长度,则write()函数返回失败。文件I/O编程lseek()函数是用于在指定的文件描述符中将文件指针定位到相应的位置。它只能用在可定位(可随机访问)文件操作中。管道、套接字和大部分字符设备文件是不可定位的,所以在这些文件的操作中无法使用lseek()调用。文件I/O编程前面讲述的系统调用是操作系统直接提供的函数接口。因为运行系统调用时,Linux必须从用户态切换到内核态,执行相应的请求,然后再返回到用户态,所以应该尽量减少系统调用的次数,从而提高程序的效率。标准I/O提供流缓冲的目的是尽可能减少使用read()和write()等系统调用的数量。文件I/O编程标准I/O提供了3种类型的缓冲存储。全缓冲:在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。对于存放在磁盘上的文件通常是由标准I/O库实施全缓冲的。行缓冲:在这种情况下,当在输入和输出中遇到行结束符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符(如fputc()函数),但只有写了一行之后才进行实际I/O操作。标准输入和标准输出就是使用行缓冲的典型例子。不带缓冲:标准I/O库不对字符进行缓冲。如果用标准I/O函数写若干字符到不带缓冲的流中,则相当于用系统调用write()函数将这些字符全写到被打开的文件上。标准出错stderr通常是不带缓存的,这就使得出错息可以尽快显示出来,而不管它们是否含有一个行结束符。文件I/O编程打开文件:三个标准函数fopen()、fdopen()和freopen()。它们可以以不同的模式打开,但都返回一个指向FILE的指针,该指针指向对应的I/O流。此后,对文件的读写都是通过这个FILE指针来进行。其中fopen()可以指定打开文件的路径和模式,fdopen()可以指定打开的文件描述符和模式,而freopen()除可指定打开的文件、模式外,还可指定特定的I/O流。文件I/O编程其中,mode定义打开文件的访问权限:文件I/O编程关闭文件:关闭标准流文件的函数为fclose(),该函数将缓冲区内的数据全部写入到文件中,并释放系统所提供的文件资源。文件I/O编程在文件流被打开之后,可对文件流进行读写等操作,其中读操作的函数为fread():文件I/O编程fwrite()函数是用于对指定的文件流进行写操作。文件I/O编程字符输入函数字符输出函数文件I/O编程行输入函数行输出函数文件I/O编程格式化输入函数文件I/O编程格式化输出函数进程控制编程进程是指一个具有独立功能的程序在某个数据集合上的一次动态执行过程,它是系统进行资源分配和调度的基本单元。一次任务的运行可以并发激活多个进程,这些进程相互合作来完成该任务的一个最终目标。进程和程序是有本质区别的:程序是静态的一段代码,是一些保存在非易失性存储器的指令的有序集合,没有任何执行的概念;而进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和消亡的整个过程,它是程序执行和资源管理的最小单位。进程控制编程进程状态转换关系:进程控制编程进程是通过进程控制块来描述的。进程控制块包含了进程的描述信息、控制信息以及资源信息,它是进程的一个静态描述。进程控制块中每一项都是一个task_struct结构。进程控制编程在Linux中,最主要的进程标识有进程号(PID,ProcessIdenityNumber)和它的父进程号(PPID,parentprocessID)。其中PID惟一地标识一个进程。PID和PPID都是非零的正整数。在Linux中获得当前进程的PID和PPID的系统调用函数为getpid()和getppid(),通常程序获得当前进程的PID和PPID之后,可以将其写入日志文件以做备份。进程控制编程进程的创建和执行许多操作系统都提供的是产生进程的机制,也就是首先在新的地址空间里创建进程、读入可执行文件,最后再开始执行。Linux中进程的创建很特别,它把上述步骤分解到两个单独的函数中取执行:fork()和exec函数族。首先,fork()通过拷贝当前进程创建一个子进程,子进程与父进程的区别仅仅在于不同的PID、PPID和某些资源及统计量。exec函数族负责读取可执行文件并将其载入地址空间开始运行。进程控制编程进程的终止进程终结也需要做很多繁琐的收尾工作,系统必须保证进程所占用的资源回收,并通知父进程。Linux首先把终止的进程设置为僵尸状态,这个时候,进程无法投入运行了,它的存在只为父进程提供信息,申请死亡。父进程得到信息后,开始调用wait函数族,最终赐死子进程,子进程占用的所有资源被全部释放。进程控制编程进程管理相关命令进程控制编程在Linux中创建一个新进程的方法是使用fork()函数。fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了

1 / 134
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功