2410开发板实验参考书_第1页
2410开发板实验参考书_第2页
2410开发板实验参考书_第3页
2410开发板实验参考书_第4页
2410开发板实验参考书_第5页
已阅读5页,还剩274页未读 继续免费阅读

下载本文档

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

文档简介

BeijingUniversalPioneeringTechnologyCo.,LTD.PAGE84TEL:010-82110740821107418211074282110743FAX:总机转828TOC\o"1-2"\h\z\u第一章嵌入式Linux开发基础知识 21.1嵌入式Linux简介 21.2嵌入式Linux开发平台简介 41.3嵌入式Linux开发流程 91.4嵌入式Linux开发环境的建立 11第二章基础实验 232.1熟悉Linux开发环境 232.2多线程应用程序设计 272.3串行端口程序设计 402.4CAN总线通讯实验 512.5简单嵌入式WEB服务器实验 64第三章图形界面应用程序设计 793.1安装与建立Qt桌面运行环境 793.2QtDesigner简介以及Qt/E的交叉编译 863.3建立本机Qtopia虚拟平台 943.4Qtopia2.1.1在2410上的移植 99第四章内核实验 1034.1Linux内核移植与编译实验 103第五章驱动模块实验 1305.1内核驱动设计入门-模块方式驱动实验 1305.2内核驱动设计实验-触摸屏驱动 1615.3SD卡使用实验 1855.4IDE_硬盘读写实验 2115.5音频驱动及应用实验 2245.6蓝牙无线通讯实验 240第六章附录 2536.1常用LINUX命令的使用 2536.2VI简介 2606.3GCC与GDB 2626.4GNU通用公共许可证(GPL1991.6第二版) 2656.5北京博创兴业科技嵌入式系统培训中心 271

第一章嵌入式Linux

开发基础知识随着后PC时代的到来,嵌入式系统技术已经成为了一个万众瞩目的焦点。目前已广泛应用于信息家电、数据网络、工业控制、医疗卫生、航空航天等众多领域。巨大的市场潜力,无穷的商机,吸引了各路英豪纷踵沓来。硬件方面,各大电子厂商相继推出了自己的专用嵌入式芯片,漫天而至的是mp3,PDA,无线上网装置,让人们充分感受到了这股强劲之势;软件方面,在Vxworks、pSOS、Neculeus和WindowsCE等嵌入式操作系统引领下,也出现了空前繁荣的局面,但这些专用操作系统都是商业化产品,其高昂的价格使许多面向低端产品的小公司望而却步,并且其源代码的封闭性也大大限制了开发者的积极性。近两年在我国登陆并蓬勃发展的Linux,也已广泛应用于各类计算应用,不仅包括IBM的微型Linux腕表、手持设备(PDA和蜂窝电话)、因特网装置、客户机、防火墙、工业机器人和电话基础设施设备,甚至还包括了基于集群的超级计算机。Linux在高端服务器的优越表现及其天生具有的突出特点,就注定它必将在低端嵌入式系统中再次给人们以惊喜,而基于嵌入式Linux操作系统的应用,必定给我们未来的工作和生活带来翻天覆地的变化。1.1嵌入式Linux简介Linux正在嵌入式开发领域稳步发展。Linux使用GPL,所有对特定开发板、PDA、掌上机、可携带设备等使用嵌入式Linux感兴趣的人都可以从因特网上免费下载其内核和应用程序,并开始移植和开发。许多Linux改良品种迎合了嵌入式市场,它们包括RTLinux(实时Linux)、uclinux(用于非MMU设备的Linux)、MontavistaLinux(用于ARM、MIPS、PPC的Linux分发版)、ARM-Linux(ARM上的Linux)和其它Linux系统。嵌入式Linux的发展比较迅速。NEC、索尼已经在销售个人视频录像机等基于Linux的消费类电子产品,摩托罗拉则计划在其未来的大多数手机上使用Linux,IBM也制定了在手持机上运行Linux的计划。数年来,“Linux标准库”组织一直在从事对在服务器上运行的Linux进行标准化的工作,现在,嵌入式计算领域也开始了这一工作。嵌入式Linux标准吸引了“Linux标准库”以及Unix组织中有益的元素。在嵌入式系统中使用Linux的优点和缺点虽然大多数Linux系统运行在PC平台上,但Linux也是嵌入式系统的可靠主力。Linux的安装和管理比UNIX更加简单灵活,这对于那些UNIX专家们来说又是一个优点,因为Linux中有许多命令和编程接口同传统的UNIX一样。但是对于习惯于WINDOWS操作系统的人来说,需要记忆大量的命令行参数却是一个缺点。随着LINUX社团的不断努力,linux的人机界面开发环境正在不断完善。典型的Linux系统经过打包,在拥有硬盘和大容量内存的PC机上运行,嵌入式系统不需要这么高的配置。一个功能完备的Linux内核要求大约1MB内存。而Linux微内核只占用其中很小一部分内存,包括虚拟内存和所有核心的操作系统功能在内,只需占用系统约100K内存。只要有500K的内存,一个有网络栈和基本实用程序的完全的Linux系统就可以在一台8位总线(SX)的Intel386微处理器上运行的很好了。由于内存要求常常是需要的应用所决定的,比如Web服务器或者SNMP代理,Linux系统甚至可以仅使用256KBROM和512KBRAM进行工作。因此它是一个瞄准嵌入式市场的轻量级操作系统。与传统的实时操作系统相比(RTOS),采用象嵌入式Linux这样的开放源码的操作系统的另外一个好处是Linux开发团体看来会比RTOS的供应商更快地支持新的IP协议和其它协议。例如,用于Linux的设备驱动程序要比用于商业操作系统的设备驱动程序多,如网络接口卡(NIC)驱动程序以及并口和串口驱动程序。核心Linux操作系统本身的微内核体系结构相当简单。网络和文件系统以模块形式置于微内核的上层。驱动程序和其它部件可在运行时作为可加载模块编译到或者是添加到内核。这为构造定制的可嵌入系统提供了高度模块化的构件方法。而在典型情况下该系统需结合定制的驱动程序和应用程序以提供附加功能。嵌入式系统也常常要求通用的功能,为了避免重复劳动,这些功能的实现运用了许多现成的程序和驱动程序,它们可以用于公共外设和应用。Linux可以在外设范围广泛的多数微处理器上运行,并早已经有了现成的应用库。Linux用于嵌入式的因特网设备也是很合适的,原因是它支持多处理器系统,该特性使Linux具有了伸缩性。因而设计人员可以选择在双处理器系统上运行实时应用,提高整体的处理能力。例如,您可以在一个处理器运行GUI,同时在另一个处理器上运行Linux系统。在嵌入式系统上运行Linux的一个缺点是Linux体系提供实时性能需要添加实时软件模块。而这些模块运行的内核空间正是操作系统实现调度策略、硬件中断异常和执行程序的部分。由于这些实时软件模块是在内核空间运行的,因此代码错误可能会破坏操作系统从而影响整个系统的可靠性,这对于实时应用将是一个非常严重的弱点。已经有许多嵌入式Linux系统的示例;可以有把握地说,某种形式的Linux能在几乎任一台执行代码的计算机上运行。1.2嵌入式Linux开发平台简介Linux价格低廉、功能强大,可以运行在X86,Alpha,Sparc,MIPS,PPC,MOTOROLA,NEC,ARM等硬件平台上,而且开放源代码,可以定制。我们所介绍的硬件平台是基于ARM体系结构,由北京博创兴业科技有限公司开发的UP-NetARM3000和UP-NetARM2410开发板。UP-NetARM3000的CPU为ARM7TDMI内核的三星S3C44B0X01芯片,由于没有MMU(内存管理单元)只能运行uClinux,UP-NetARM2410开发板的CPU为ARM920T内核的三星S3c2410芯片,由于有MMU可以运行标准的ARM-LINUX内核。通过这两个平台,我们可以学习嵌入式LINUX中的针对有MMU和无MMU的不同开发过程。UP-NetARM3000及相关产品的资料可以访问博创公司的网站获得。本书以UP-NetARM2410开发板为例,详细介绍嵌入式Linux的开发过程。UP-NetARM2410开发板实验仪器介绍硬件配置UP-NetARM2410开发板的硬件配置如表1.2.1所示,实物如图1配置名称型号说明CPUARM920T结构芯片三星S3c2410X工作频率203MHzFLASHSAMSUNGK9F120864MSDRAMHY57V561620AT-H32M×2=64MEtherNet网卡DM9000AEP10/100M自适应LCD(可选)一个32脚薄膜线插座触摸屏(可选)一个8脚触摸屏插座FM7843驱动LED两个小数码管和3个发光二极管USB接口1个HOST/1个DEVICEUART2个RS232从处理器的UART2引出AD由S3C2410芯片引出板载两个分压精密电位器AUDIOIIS总线,UDA1341芯片44.1KHz音频扩展插座3个40PinEXPORT总线直接扩展IDE/CF卡接口IDE硬盘接口,CF(IDE模式)卡MMC和SD卡接口调试接口JTAG14针按键三个可产生中断的按键2片IIC存储器AT24C01CANBUS由MCP2510和TJA1050构成PWM和DA输出MAX504两路PWM输出和DA电路DC5V电源输入具备LDO产生3.3V和1.8V的电压备有RESET、RTC电路表1.2.1UP-NetARM2410的硬件配置图1.2.1UP-NetARM2410S3c2410芯片介绍S3c2410X芯片集成了大量的功能单元,包括:1.内部1.8V,存储器3.3V,外部IO3.3V,16KB数据CACH,16KB指令CACH,MMU;2.内置外部存储器控制器(SDRAM控制和芯片选择逻辑);3.LCD控制器(最高4K色STN和256K彩色TFT),一个LCD专用DMA;4.4路带外部请求线的DMA;5.三个通用异步串行端口(IrDA1.0,16-ByteTxFIFO,and16-ByteRxFIFO),2通道SPI;6.一个多主IIC总线,一个IIS总线控制器;7.SD主接口版本1.0和多媒体卡协议版本2.11兼容;8.2个USBHOST,一个USBDEVICE(VER1.1);9.4个PWM定时器和一个内部定时器;10.看门狗定时器;11.117个通用IO;12.24个外部中断;13.电源控制模式:标准、慢速、休眠、掉电;14.8通道10位ADC和触摸屏接口;15.带日历功能的实时时钟;16.芯片内置PLL;17.设计用于手持设备和通用嵌入式系统;18.16/32位RISC体系结构,使用ARM920TCPU核的强大指令集;19.ARM带MMU的先进的体系结构支持WINCE、EPOC32、LINUX;20.指令缓存(cache)、数据缓存、写缓冲和物理地址TAGRAM,减小了对主存储器带宽和性能的影响;21.ARM920TCPU核支持ARM调试的体系结构;22.内部先进的位控制器总线(AMBA2.0,AHB/APB).其结构图如图1.2.图1.2.2S3c2410系统管理:1.小端/大端支持;2.地址空间:每个BANK128MB(全部1G字节);3.每个BANK可编程为8/16/32位数据总线;4.bank0到bank6为固定起始地址;5.bank7可编程BANK起始地址和大小;6.一共8个存储器BANK;7.6个存储器BANK用于ROM,SRAM和其他;8.2个存储器BANK用于ROM,SRAM和同步DRAM;9.每个存储器BANK可编程存取周期;10.支持等待信号用以扩展总线周期;11.支持SDRAM掉电模式下的自刷新;12.支持不同类型的ROM用于启动NOR/NANDFlash,EEPROM和其他。芯片封装:272-FBGA封装图如图1.2.图1.2.3272-FBGA封装1.3嵌入式Linux开发流程嵌入式linux开发,根据应用需求的不同有不同的配置开发方法,但是一般都要经过以下过程:建立开发环境。操作系统一般使用REDHAT-LINUX,版本7到9都可以,选择定制安装或全部安装,通过网络下载相应的GCC交叉编译器进行安装(比如arm-linux-gcc、arm-uclibc-gcc),或者安装产品厂家提供的交叉编译器。配置开发主机。配置MINICOM,一般参数为波特率115200,数据位8位,停止位1,无奇偶校验,软硬件控制流设为无。在WINDOWS下的超级终端的配置也是这样。MINICOM软件的作用是作为调试嵌入式开发板信息输出的监视器和键盘输入的工具;配置网络,主要是配置NFS网络文件系统,需要关闭防火墙,简化嵌入式网络调试环境设置过程。建立引导装载程序BOOTLOADER,从网络上下载一些公开源代码的BOOTLOADER,如U-BOOT、BLOB、VIVI、LILO、ARM-BOOT、RED-BOOT等,根据自己具体芯片进行移植修改。有些芯片没有内置引导装载程序,比如三星的ARM7、ARM9系列芯片,这样就需要编写烧写开发板上flash的烧写程序,网络上有免费下载的WINDOWS下通过JTAG并口简易仿真器烧写ARM外围flash芯片的程序。也有LINUX下公开源代码的J-FLASH程序。如果不能烧写自己的开发板,就需要根据自己的具体电路进行源代码修改。这是让系统可以正常运行的第一步。如果你购买了厂家的仿真器当然比较容易烧写flash了,但是其中的核心技术是无法了解的。这对于需要迅速开发应用的人来说可以极大地提高开发速度。下载别人已经移植好的LINUX操作系统,如UCLINUX、ARM-LINUX、PPC-LINUX等,如果有专门针对你所使用的CPU移植好的LINUX操作系统那是再好不过,下载后再添加自己的特定硬件的驱动程序,进行调试修改,对于带MMU的CPU可以使用模块方式调试驱动,对于UCLINUX这样的系统好像只能编译进内核进行调试。建立根文件系统,从下载使用BUSYBOX软件进行功能裁减,产生一个最基本的根文件系统,再根据自己的应用需要添加其他的程序。默认的启动脚本一般都不会符合应用的需要,所以就要修改根文件系统中的启动脚本,它的存放位置位于/etc目录下,包括:/etc/init.d/rc.S、/etc/profile、/etc/.profile等,自动挂装文件系统的配置文件/etc/fstab,具体情况会随系统不同而不同。根文件系统在嵌入式系统中一般设为只读,需要使用mkcramfs、genromfs等工具产生烧写映象文件。建立应用程序的flash磁盘分区,一般使用JFFS2或YAFFS文件系统,这需要在内核中提供这些文件系统的驱动,有的系统使用一个线性flash(NOR型)512K-32M,有的系统使用非线性flash(NAND型)8-512M,有的两个同时使用,需要根据应用规划flash的分区方案。开发应用程序,可以下载到根文件系统中,也可以放入YAFFS、JFFS2文件系统中,有的应用程序不使用根文件系统,而是直接将应用程序和内核设计在一起,这有点类似于UCOS-II的方式。烧写内核、根文件系统、应用程序。发布产品。1.4嵌入式Linux开发环境的建立嵌入式LINUX开发环境有几个方案:1、基于PC机WINDOWS操作系统下的CYGWIN;2、在WINDOWS下安装虚拟机后,再在虚拟机中安装LINXUX操作系统;3、直接安装LINUX操作系统。基于WINDOWS的环境要么有兼容性问题,要么速度有影响,所以推荐大家使用纯LINUX操作系统开发环境。我们实际的开发环境为REDHAT9,它已经支持中文,并且包含了绝大部分的开发工具,不用担心装了LINUX就不能使用WINDOWS的问题。一般的情况都是用户已经有了WINDOWS操作系统,再安装LINUX,LINUX会自动安装一个叫作GRUB的启动引导软件,可以选择引导多个操作系统。预备知识绝大多数Linux软件开发都是以native方式进行的,即本机(HOST)开发、调试,本机运行的方式。这种方式通常不适合于嵌入式系统的软件开发,因为对于嵌入式系统的开发,没有足够的资源在本机(即板子上系统)运行开发工具和调试工具。通常的嵌入式系统的软件开发采用一种交叉编译调试的方式。交叉编译调试环境建立在宿主机(即一台PC机)上,对应的开发板叫做目标板。运行Linux的PC【宿主机】开发时使用宿主机上的交叉编译、汇编及连接工具形成可执行的二进制代码(这种可执行代码并不能在宿主机上执行,而只能在目标板上执行),然后把可执行文件下载到目标机上运行。调试时的方法很多,可以使用串口,以太网口等,具体使用哪种调试方法可以根据目标机处理器提供的支持作出选择。宿主机和目标板的处理器一般不相同,宿主机为Intel处理器,而目标板如UP-NetARM2410开发板为三星S3c2410.GNU编译器提供这样的功能,在编译器编译时可以选择开发所需的宿主机和目标机从而建立开发环境。所以在进行嵌入式开发前第一步的工作就是要安装一台装有指定操作系统的PC机作宿主开发机,对于嵌入式LINUX,宿主机上的操作系统一般要求为REDHATLINUX。嵌入式开发通常要求宿主机配置有网络,支持NFS(为交叉开发时mount所用)。然后要在宿主机上建立交叉编译调试的开发环境。环境的建立需要许多的软件模块协同工作,这将是一个比较繁杂的工作,但现在已通过博创嵌入式教学套件中光盘的安装而自动完成了。对开发PC机的性能要求由于Redhat9.0安装后占用空间约为2.4G-5G之间,还要安装ARM-LINUX硬件要求:CPU:高于奔腾500M,推荐高于赛扬1.7G;内存:大于128M,推荐256M;硬盘:大于10G,推荐高于40G。开发工具软件的安装与配置1.REDHATLINUX9.0的安装在一台PC上安装RedHatLINUX9.0,选择Custom定制安装,在选择软件Package时最好将所有包都安装,需要空间约2.7G,如果选择最后一项:everything,即完全安装,将安装3张光盘的全部软件,需要磁盘空间大约5G。因此建议提前为REDHATLINUX的安装预留大约5-15G的空间,具体视用户的硬盘空间大小来确定,在安装完Redhat后还要安装Linux的编译器和开发库以及ARM-Linux的所有源代码,这些包安装后的总共需要空间大约为800M。2.开发工具软件的安装将博创兴业科技有限公司提供的附带开发工具光盘插入CDROM,然后执行以下命令:mount/dev/cdrom/mnt若系统不识别/dev/cdrom的话,可以用如下命令,假设CDROM为从盘,即为/dev/hdb,则:mount–tiso9660/dev/hdb/mnt安装脚本程序将自动建立/arm2410s目录,并将所有开发软件包安装到/arm2410s目录下,同时自动配置编译环境,建立合适的符号连接。注意:安装完成后看一下主编译器Armv4l-unknown-linux-gcc是否在/opt/host/armv4l/bin/,如果不是这个路径,请使用vi修改/root/.bash_profile文件中PATH变量为PATH=$PATH:$HOME/bin:/opt/host/armv4l/bin/,存盘后执行:source/root/.bash_profile,则以后armv4l-unknown-linux-gcc会自动搜索到,可以在终端上输入armv,然后按tab键,会自动显示armv4l-unknown-linux-3.开发环境配置配置网络,包括配置IP地址、NFS服务、防火墙。网络配置主要是要安装好以太网卡,对于一般常见的RTL8139网卡,REDHAT9.0可以自动识别并自动安装好,完全不要用户参与,因此建议使用该网卡。然后配置宿主机IP为21。如果是在有多台计算机使用的局域网环境使用此开发设备,IP地址可以根据具体情况设置。如图1.4.1图1.4.1双击设备eth0的蓝色区域,进入以太网设置界面,如图1.4.2,1.4.3图1.4.2图1.4.3对于REDHAT9.0,它默认的是打开了防火墙,因此对于外来的IP访问它全部拒绝,这样其它网络设备根本无法访问它,即无法用NFSmount它,许多网络功能都将无法使用。因此网络安装完毕后,应立即关闭防火墙。操作如下:点击红帽子开始菜单,选择安全级别设置,选中无防火墙。如图1.4.4图1.4.4在系统设置菜单中选择服务器设置菜单,再选中服务菜单,将iptables服务的勾去掉,并确保nfs选项选中。配置NFS:点击主菜单运行系统设置->服务器设置->NFS服务器(英文为:SETUP->SYSTEMSERVICE->NFS),点击增加出现如下在界面,在目录(Drictory):中填入需要共享的路径,在主机(Hosts):中填入允许进行连接的主机IP地址。并选择允许客户对共享目录的操作为只读(Read-only)或读写(Read/write)。如图1.4.5图1.4.5NFS图1.4.图1.4.6当将远程根用户当作本地根用户时,对于操作比较方便,但是安全性较差。最后退出时则完成NFS配置。配置好后,界面应显示如图1.4.图1.4.7图1.4.8我们也可以手工编写/etc/exports文件,其格式如下:共享目录可以连接的主机(读写权限,其他参数)例如:/arm2410s192.168.0.*(rw,sync)表示将本机的/arm2410s目录共享给ip地址为-54的所有计算机,可以读取和写入。配置完成后,可用如下办法简单测试一下NFS是否配置好了:在宿主机上自己mount自己,看是否成功就可以判断NFS是否配好了。例如在宿主机/目录下执行:mount0:/arm2410s/mnt其中0应为主机的IP地址。然后到/mnt/目录下看是否可以列出/arm2410s目录下的所有文件和目录,可以则说明mount成功,NFS配置成功。配置MINICOM:1.在linux操作系统Xwindow界面下建立终端(在桌面上点击右键——>新建终端),在终端的命令行提示符后输入minicom,图1.4.9minicom启动画面2.minicom启动后,先按Ctrl+A键,再按Z键(注意不是连续按,Ctrl+A松开后才按Z),进入主配置界面(见图1.4.10)。图1.4.10主配置界面按“O”进入配置界面,如图1.4.11配置界面图1.4.11按上下键选择Serialportsetup,进入端口设置界面,这里有几个重要选项改为如下值(见图1.4.12):(在Changewhichsetting后按哪个字母就进入哪项的配置,如按A进行端口号配置。)A————SerialDevice:/dev/ttyS0(端口号使用串口1)E————BPS/par/bits:/1152008N1(波特率)F,E硬件流,软件流都改为NO,若要使用PC机的串口2来接板子的串口1做监控,改为:/dev/ttyS1即可。3.选好后按ESC键退出到图1.4.11所示画面,选择Savesetupasdf1保存退出,以后只要启动minicom就是该配置,无需再做改动。4.配置完成后,用串口线连接好pc机和2410开发板,启动2410开发板,即可在minicom上看到启动信息,并可以执行操作控制。图1.4.12端口设置界面

Linux开发软件的安装目录结构表格1.4.1均以/arm2410s表1.4.1/arm2410s目录名说明busybox-1.00-pre10Busybox-1.00源代码docarm2410linux使用说明书QtQt应用程序和库的源代码insight-6.0Linux下源代码查看器root2410平台根文件系统kernel-2410s2410平台linux内核源代码demos所有实验演示程序imgvivi系统引导程序zImageARMLINUX-2.4内核压缩映象文件root.cramfs根文件系统映象文件yaffs.tar.bz2demos演示程序的压缩文件exp实验例程源码shmount-dos.shlinux下挂装windows的分区示例脚本 linux下挂装windows的分区示例脚本。mnt_udisk.shMOUNTU盘mkroot.sh制作根文件系统的脚本编译器安装路径说明如表1.4.2表1.4.2编译器安装目录说明arm-elf-gcc-2.95.3/opt/host/armv4l应用开发库和头文件Armv4l-unknown-linux-gcc/opt/host/armv4l/bin主编译器上述诸多程序的源代码都在光盘中提供.在安装完成LINUX后,就是对LINUX的网络环境的配置,最主要是配置NFS服务器。第二章基础实验2.1熟悉Linux开发环境一、实验目的熟悉Linux开发环境,学会基于S3C2410的Linux开发环境的配置和使用。使用Linux的armv4l-unknown-linux-gcc编译,使用基于NFS方式的下载调试,了解嵌入式开发的基本过程。二、实验内容本次实验使用RedhatLinux9.0操作系统环境,安装ARM-Linux的开发库及编译器。创建一个新目录,并在其中编写hello.c和Makefile文件。学习在Linux下的编程和编译过程,以及ARM开发板的使用和开发环境的设置。下载已经编译好的文件到目标开发板上运行。三、预备知识C语言的基础知识、程序调试的基础知识和方法,Linux的基本操作。四、实验设备及工具(包括软件调试工具)硬件:UP-NETARM2410嵌入式实验平台、PC机Pentium500以上,硬盘10G以上。软件:PC机操作系统REDHATLINUX9.0+MINICOM+ARM-LINUX开发环境五、实验步骤1、建立工作目录[root@zxtsmile]#mkdirhello[root@zxtsmile]#cdhello2、编写程序源代码在Linux下的文本编辑器有许多,常用的是vim和Xwindow界面下的gedit等,我们在开发过程中推荐使用vim,用户需要学习vim的操作方法,请参考相关书籍中的关于vim的操作指南。Kdevelope、anjuta软件的界面与vc6.0类似,使用它们对于熟悉windows环境下开发的用户更容易上手。实际的hello.c源代码较简单,如下:#include<stdio.h>main(){ printf(“helloworld\n”);}我们可以是用下面的命令来编写hello.c的源代码,进入hello目录使用vi命令来编辑代码:[root@zxthello]#vihello.c按“i”或者“a”进入编辑模式,将上面的代码录入进去,完成后按Esc键进入命令状态,再用命令“:wq”保存并退出。这样我们便在当前目录下建立了一个名为hello.c的文件。3、编写Makefile要使上面的hello.c程序能够运行,我们必须要编写一个Makefile文件,Makefile文件定义了一系列的规则,它指明了哪些文件需要编译,哪些文件需要先编译,哪些文件需要重新编译等等更为复杂的命令。使用它带来的好处就是自动编译,你只需要敲一个“make”命令整个工程就可以实现自动编译,当然我们本次实验只有一个文件,它还不能体现出使用Makefile的优越性,但当工程比较大文件比较多时,不使用Makefile几乎是不可能的。下面我们介绍本次实验用到的Makefile文件。CC=armv4l-unknown-linux-gccEXEC=helloOBJS=hello.oCFLAGS+=LDFLAGS+=–staticall:$(EXEC)$(EXEC):$(OBJS) $(CC)$(LDFLAGS)-o$@$(OBJS)clean: -rm-f$(EXEC)*.elf*.gdb*.o下面我们来简单介绍这个Makefile文件的几个主要部分:CC指明编译器EXEC表示编译后生成的执行文件名称OBJS目标文件列表CFLAGS编译参数LDFLAGS连接参数all:编译主入口clean:清除编译结果注意:“$(CC)$(LDFLAGS)-o$@$(OBJS)”和“-rm-f$(EXEC)*.elf*.gdb*.o”前空白由一个Tab制表符生成,不能单纯由空格来代替。与上面编写hello.c的过程类似,用vi来创建一个Makefile文件并将代码录入其中[root@zxthello]#viMakefile4、编译应用程序在上面的步骤完成后,我们就可以在hello目录下运行“make”来编译我们的程序了。如果进行了修改,重新编译则运行:[root@zxthello]#makeclean[root@zxthello]#make注意:编译、修改程序都是在宿主机(本地PC机)上进行,不能在MINICOM下进行。5、下载调试在宿主PC计算机上启动NFS服务,并设置好共享的目录,具体配置请参照前面第一章第四节中关于嵌入式Linux环境开发环境的建立。在建立好NFS共享目录以后,我们就可以进入MINICOM中建立开发板与宿主PC机之间的通讯了。[root@zxthello]#minicom[/mnt/yaffs]mount-tnfs-onolock6:/arm2410s/host注意:IP地址需要根据宿主PC机的实际情况修改成功挂接宿主机的arm2410s目录后,在开发板上进入/host目录便相应进入宿主机的/arm2410s目录,我们已经给出了编辑好的hello.c和Makefile文件,它们在/arm2410s/exp/basic/01_hello目录下。用户可以直接在宿主PC上编译生成可执行文件,并通过上面的命令挂载到开发板上,运行程序察看结果。如果不想使用我们提供的源码的话,可以再建立一个NFS共享文件夹。如/root/share,我们把我们自己编译生成的可执行文件复制到该文件夹下,并通过MINICOM挂载到开发板上。[root@zxthello]#cphello/root/share[root@zxthello]#minicom[/mnt/yaffs]mount-tnfs-onolock6:/root/share/host再进入/host目录运行刚刚编译好的hello程序,查看运行结果。[/mnt/yaffs]cd/host[/host]./hellohelloworld注意:开发板挂接宿主计算机目录只需要挂接一次便可,只要开发板没有重起,就可以一直保持连接。这样可以反复修改、编译、调试,不需要下载到开发板。六、思考题1.Makefile是如何工作的?其中的宏定义分别是什么意思?

2.2多线程应用程序设计一、实验目的了解多线程程序设计的基本原理。学习pthread库函数的使用。二、实验内容读懂pthread.c的源代码,熟悉几个重要的PTHREAD库函数的使用。掌握共享锁和信号量的使用方法。进入/arm2410s/exp/basic/02_pthread目录,运行make产生pthread程序,使用NFS方式连接开发主机进行运行实验。三、预备知识有C语言基础掌握在Linux下常用编辑器的使用掌握Makefile的编写和使用掌握Linux下的程序编译与交叉编译过程四、实验设备及工具硬件:UP-NETARM2410嵌入式实验平台,PC机Pentium500以上,硬盘40G以上,内存大于128M。软件:PC机操作系统REDHATLINUX9.0+MINICOM+ARM-LINUX开发环境五、实验原理及代码分析1.多线程程序的优缺点多线程程序作为一种多任务、并发的工作方式,有以下的优点:1)提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(timeconsuming)置于一个新的线程,可以避免这种尴尬的情况。2)使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。3)改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。LIBC中的pthread库提供了大量的API函数,为用户编写应用程序提供支持。2.实验源代码与结构流程图本实验为著名的生产者-消费者问题模型的实现,主程序中分别启动生产者线程和消费者线程。生产者线程不断顺序地将0到1000的数字写入共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区读取数据。流程图如图2.2.1所示:图2.2.1生产者-消费者实验源代码结构流程图本实验具体代码如下:/************************************************* Theclassicproducer-consumerexample.* Illustratesmutexesandconditions.*byZoujianguo<ah_zou@>*2003-12-22*************************************************/#include<stdio.h>#include<stdlib.h>#include<time.h>#include"pthread.h"#defineBUFFER_SIZE16/*设置一个整数的圆形缓冲区*/structprodcons{intbuffer[BUFFER_SIZE];/*缓冲区数组*/pthread_mutex_tlock;/*互斥锁*/intreadpos,writepos;/*读写的位置*/pthread_cond_tnotempty;/*缓冲区非空信号*/pthread_cond_tnotfull;/*缓冲区非满信号*/};/**//*初始化缓冲区*/voidinit(structprodcons*b){pthread_mutex_init(&b->lock,NULL);pthread_cond_init(&b->notempty,NULL);pthread_cond_init(&b->notfull,NULL);b->readpos=0;b->writepos=0;}/**//*向缓冲区中写入一个整数*/voidput(structprodcons*b,intdata){ pthread_mutex_lock(&b->lock); /*等待缓冲区非满*/ while((b->writepos+1)%BUFFER_SIZE==b->readpos){ printf("waitfornotfull\n"); pthread_cond_wait(&b->notfull,&b->lock); }/*写数据并且指针前移*/ b->buffer[b->writepos]=data; b->writepos++; if(b->writepos>=BUFFER_SIZE)b->writepos=0;/*设置缓冲区非空信号*/ pthread_cond_signal(&b->notempty); pthread_mutex_unlock(&b->lock);}/**//*从缓冲区中读出一个整数*/intget(structprodcons*b){ intdata; pthread_mutex_lock(&b->lock); /*等待缓冲区非空*/ while(b->writepos==b->readpos){ printf("waitfornotempty\n"); pthread_cond_wait(&b->notempty,&b->lock); } /*读数据并且指针前移*/ data=b->buffer[b->readpos]; b->readpos++; if(b->readpos>=BUFFER_SIZE)b->readpos=0; /*设置缓冲区非满信号*/ pthread_cond_signal(&b->notfull); pthread_mutex_unlock(&b->lock); returndata;}/**/#defineOVER(-1)structprodconsbuffer;/**/void*producer(void*data){ intn; for(n=0;n<1000;n++){ printf("put-->%d\n",n); put(&buffer,n); }put(&buffer,OVER);printf("producerstopped!\n");returnNULL;}/**/void*consumer(void*data){intd;while(1){d=get(&buffer);if(d==OVER)break;printf("%d-->get\n",d);}printf("consumerstopped!\n");returnNULL;}/**/intmain(void){ pthread_tth_a,th_b; void*retval; init(&buffer); pthread_create(&th_a,NULL,producer,0); pthread_create(&th_b,NULL,consumer,0);/*等待生产者和消费者结束*/ pthread_join(th_a,&retval); pthread_join(th_b,&retval); return0;}3.主要函数分析:下面我们来看一下,生产者写入缓冲区和消费者从缓冲区读数的具体流程,生产者首先要获得互斥锁,并且判断写指针+1后是否等于读指针,如果相等则进入等待状态,等候条件变量notfull;如果不等则向缓冲区中写一个整数,并且设置条件变量为notempty,最后释放互斥锁。消费者线程与生产者线程类似,这里就不再过多介绍了。流程图如下:图2.2.2生产消费流程图生产者写入共享的循环缓冲区函数PUTvoidput(structprodcons*b,intdata){ pthread_mutex_lock(&b->lock);//获取互斥锁 while((b->writepos+1)%BUFFER_SIZE==b->readpos){//如果读写位置相同 pthread_cond_wait(&b->notfull,&b->lock);//等待状态变量b->notfull,不满则跳出阻塞 } b->buffer[b->writepos]=data;//写入数据 b->writepos++; if(b->writepos>=BUFFER_SIZE)b->writepos=0; pthread_cond_signal(&b->notempty);//设置状态变量 pthread_mutex_unlock(&b->lock);//释放互斥锁}消费者读取共享的循环缓冲区函数GETintget(structprodcons*b){ intdata; pthread_mutex_lock(&b->lock);//获取互斥锁 while(b->writepos==b->readpos){//如果读写位置相同 pthread_cond_wait(&b->notempty,&b->lock);//等待状态变量b->notempty,不空则跳出阻塞。否则无数据可读。 } data=b->buffer[b->readpos];//读取数据 b->readpos++; if(b->readpos>=BUFFER_SIZE)b->readpos=0; pthread_cond_signal(&b->notfull);//设置状态变量 pthread_mutex_unlock(&b->lock);//释放互斥锁 returndata;}4.主要的多线程API在本程序的代码中大量的使用了线程函数,如pthread_cond_signal、pthread_mutex_init、pthread_mutex_lock等等,这些函数的作用是什么,在哪里定义的,我们将在下面的内容中为大家做一个简单的介绍,并且为其中比较重要的函数做一些详细的说明。线程创建函数:intpthread_create(pthread_t*thread_id,__constpthread_attr_t*__attr, void*(*__start_routine)(void*),void*__restrict__arg)获得父进程ID:pthread_tpthread_self(void)测试两个线程号是否相同:intpthread_equal(pthread_t__thread1,pthread_t__thread2)线程退出:voidpthread_exit(void*__retval)等待指定的线程结束:intpthread_join(pthread_t__th,void**__thread_return)互斥量初始化:pthread_mutex_init(pthread_mutex_t*,__constpthread_mutexattr_t*)销毁互斥量:intpthread_mutex_destroy(pthread_mutex_t*__mutex)再试一次获得对互斥量的锁定(非阻塞):intpthread_mutex_trylock(pthread_mutex_t*__mutex)锁定互斥量(阻塞):intpthread_mutex_lock(pthread_mutex_t*__mutex)解锁互斥量:intpthread_mutex_unlock(pthread_mutex_t*__mutex)条件变量初始化:intpthread_cond_init(pthread_cond_t*__restrict__cond,__constpthread_condattr_t*__restrict__cond_attr)销毁条件变量COND:intpthread_cond_destroy(pthread_cond_t*__cond)唤醒线程等待条件变量:intpthread_cond_signal(pthread_cond_t*__cond)等待条件变量(阻塞):intpthread_cond_wait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex)在指定的时间到达前等待条件变量:intpthread_cond_timedwait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex,__conststructtimespec*__restrict__abstime)PTHREAD库中还有大量的API函数,用户可以参考其他相关书籍。下面我们对几个比较重要的函数做一下详细的说明:pthread_create线程创建函数intpthread_create(pthread_t*thread_id,__constpthread_attr_t*__attr, void*(*__start_routine)(void*),void*__restrict__arg)线程创建函数第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。pthread_join函数用来等待一个线程的结束。函数原型为:intpthread_join(pthread_t__th,void**__thread_return)第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。pthread_exit函数一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:voidpthread_exit(void*__retval)唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。下面我们来介绍有关条件变量的内容。使用互斥锁来可实现线程间数据的共享和通信,互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线线程间的同步。pthread_cond_init函数条件变量的结构为pthread_cond_t,函数pthread_cond_init()被用来初始化一个条件变量。它的原型为:intpthread_cond_init(pthread_cond_t*cond,__constpthread_condattr_t*cond_attr)其中cond是一个指向结构pthread_cond_t的指针,cond_attr是一个指向结构pthread_condattr_t的指针。结构pthread_condattr_t是条件变量的属性结构,和互斥锁一样我们可以用它来设置条件变量是进程内可用还是进程间可用,默认值是PTHREAD_PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用。注意初始化条件变量只有未被使用时才能重新初始化或被释放。释放一个条件变量的函数为pthread_cond_destroy(pthread_cond_tcond)。pthread_cond_wait函数使线程阻塞在一个条件变量上。它的函数原型为:externintpthread_cond_wait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex)线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒,但是要注意的是,条件变量只是起阻塞和唤醒线程的作用,具体的判断条件还需用户给出,例如一个变量是否为0等等,这一点我们从后面的例子中可以看到。线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。这个过程一般用while语句实现。pthread_cond_timedwait函数另一个用来阻塞线程的函数是pthread_cond_timedwait(),它的原型为:externintpthread_cond_timedwait__P((pthread_cond_t*__cond,pthread_mutex_t*__mutex,__conststructtimespec*__abstime))它比函数pthread_cond_wait()多了一个时间参数,经历abstime段时间后,即使条件变量不满足,阻塞也被解除。pthread_cond_signal函数它的函数原型为:externintpthread_cond_signal(pthread_cond_t*__cond)它用来释放被阻塞在条件变量cond上的一个线程。多个线程阻塞在此条件变量上时,哪一个线程被唤醒是由线程的调度策略所决定的。要注意的是,必须用保护条件变量的互斥锁来保护这个函数,否则条件满足信号又可能在测试条件和调用pthread_cond_wait函数之间被发出,从而造成无限制的等待。六、实验步骤1、阅读源代及编译应用程序进入exp/basic/02_pthread目录,使用vi编辑器或其他编辑器阅读理解源代码。运行make产生pthread可执行文件。2、下载和调试切换到minicom终端窗口,使用NFSmount开发主机的/arm2410s到/host目录。进入/host/exp/basic/pthread目录,运行pthread,观察运行结果的正确性。运行程序最后一部分结果如下:waitfornotemptyput-->994put-->995put-->996put-->997put-->998put-->999producerstopped!993-->get994-->get995-->get996-->get997-->get998-->get999-->getconsumerstopped![/host/exp/basic/02_pthread]七、思考题1.加入一个新的线程用于处理键盘的输入,并在按键为ESC时终止所有线程。2.线程的优先级的控制。

2.3串行端口程序设计一、实验目的了解在linux环境下串行程序设计的基本方法。掌握终端的主要属性及设置方法,熟悉终端I/O函数的使用。学习使用多线程来完成串口的收发处理。二、实验内容读懂程序源代码,学习终端I/O函数的使用方法,学习将多线程编程应用到串口的接收和发送程序设计中。三、预备知识有C语言基础。掌握在Linux下常用编辑器的使用。掌握Makefile的编写和使用。掌握Linux下的程序编译与交叉编译过程四、实验设备及工具硬件:UP-NETARM2410嵌入式实验平台、PC机Pentium500以上,硬盘10G以上。软件:PC机操作系统REDHATLINUX9.0+MINICOM+ARM-LINUX开发环境五、实验原理异步串行I/O方式是将传输数据的每个字符一位接一位(例如先低位、后高位)地传送。数据的各不同位可以分时使用同一传输通道,因此串行I/O可以减少信号连线,最少用一对线即可进行。接收方对于同一根线上一连串的数字信号,首先要分割成位,再按位组成字符。为了恢复发送的信息,双方必须协调工作。在微型计算机中大量使用异步串行I/O方式,双方使用各自的时钟信号,而且允许时钟频率有一定误差,因此实现较容易。但是由于每个字符都要独立确定起始和结束(即每个字符都要重新同步),字符和字符间还可能有长度不定的空闲时间,因此效率较低。图2.3.1串行通信字符格式图2.3.1给出异步串行通信中一个字符的传送格式。开始前,线路处于空闲状态,送出连续“1”。传送开始时首先发一个“0”作为起始位,然后出现在通信线上的是字符的二进制编码数据。每个字符的数据位长可以约定为5位、6位、7位或8位,一般采用ASCII编码。后面是奇偶校验位,根据约定,用奇偶校验位将所传字符中为“1”的位数凑成奇数个或偶数个。也可以约定不要奇偶校验,这样就取消奇偶校验位。最后是表示停止位的“1”信号,这个停止位可以约定持续1位、1.5位或2位的时间宽度。至此一个字符传送完毕,线路又进入空闲,持续为“1”。经过一段随机的时间后,下一个字符开始传送才又发出起始位。每一个数据位的宽度等于传送波特率的倒数。微机异步串行通信中,常用的波特率为50,95,110,150,300,600,1200,2400,4800,9600等。接收方按约定的格式接收数据,并进行检查,可以查出以下三种错误:奇偶错:在约定奇偶检查的情况下,接收到的字符奇偶状态和约定不符。帧格式错:一个字符从起始位到停止位的总位数不对。溢出错:若先接收的字符尚未被微机读取,后面的字符又传送过来,则产生溢出错。每一种错误都会给出相应的出错信息,提示用户处理。一般串口调试都使用空的MODEM连接电缆,其连接方式如下:图2.3.2实用RS-232C通讯连线六、程序分析Linux操作系统从一开始就对串行口提供了很好的支持,为进行串行通讯提供了大量的函数,我们的实验主要是为掌握在Linux中进行串行通讯编程的基本方法。本实验的程序流程图如下:图2.3.3串口通讯实验流程图本实验的代码如下:#include<termios.h>#include<stdio.h>#include<unistd.h>#include<fcntl.h>#include<sys/signal.h>#include<pthread.h>#defineBAUDRATEB115200#defineCOM1"/dev/ttyS0"#defineCOM2"/dev/ttyS1"#defineENDMINITERM27/*ESCtoquitminiterm*/#defineFALSE0#defineTRUE1volatileintSTOP=FALSE;volatileintfd;voidchild_handler(ints){printf("stop!!!\n");STOP=TRUE;}/**/void*keyboard(void*data){intc; for(;;){ c=getchar(); if(c==ENDMINITERM){ STOP=TRUE; break; } }returnNULL;}/**//*modeminputhandler*/void*receive(void*data){ intc; printf("readmodem\n"); while(STOP==FALSE) { read(fd,&c,1);/*comport*/ write(1,&c,1);/*stdout*/ } printf("exitfromreadingmodem\n"); returnNULL;}/**/void*send(void*data){ intc='0'; printf("senddata\n"); while(STOP==FALSE)/*modeminputhandler*/ { c++; c%=255; write(fd,&c,1);/*stdout*/ usleep(100000); } returnNULL;}/**/intmain(intargc,char**argv){ structtermiosoldtio,newtio,oldstdtio,newstdtio; structsigactionsa; intok; pthread_tth_a,th_b,th_c; void*retval; if(argc>1) fd=open(COM2,O_RDWR); else fd=open(COM1,O_RDWR);//|O_NOCTTY|O_NONBLOCK); if(fd<0){ error(COM1); exit(-1); } tcgetattr(0,&oldstdtio); tcgetattr(fd,&oldtio);/*savecurrentmodemsettings*/ tcgetattr(fd,&newstdtio);/*getworkingstdtio*/ newtio.c_cflag=BAUDRATE|CRTSCTS|CS8|CLOCAL|CREAD;/*ctrolflag*/ newtio.c_iflag=IGNPAR;/*inputflag*/ newtio.c_oflag=0; /*outputflag*/ newtio.c_lflag=0; newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0;/*nowcleanthemodemlineandactivatethesettingsformodem*/ tcflush(fd,TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);/*setattrib*/ sa.sa_handler=child_handler; sa.sa_flags=0; sigaction(SIGCHLD,&sa,NULL);/*handledyingchild*/ pthread_create(&th_a,NULL,keyboard,0); pthread_create(&th_b,NULL,receive,0); pthread_create(&th_c,NULL,send,0); pthread_join(th_a,&retval); pthread_join(th_b,&retval); pthread_join(th_c,&retval); tcsetattr(fd,TCSANOW,&oldtio);/*restoreoldmodemsetings*/ tcsetattr(0,TCSANOW,&oldstdtio);/*restoreoldttysetings*/ close(fd); exit(0);}下面我们对这个程序的主要部分做一下简单的分析头文件#include<stdio.h>/*标准输入输出定义*/#include<stdlib.h>/*标准函数库定义*/#include<unistd.h>/*linux标准函数定义*/#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>/*文件控制定义*/#include<termios.h>/*PPSIX终端控制定义*/#include<errno.h>/*错误号定义*/#include <pthread.h> /*线程库定义*/打开串口在Linux下串口文件位于/dev下,一般在老版本的内核中串口一为/dev/ttyS0,串口二为/dev/ttyS1,在我们的开发板中串口设备位于/dev/tts/下,因为开发板中没有ttyS0这个设备,所以我们要建立一个连接,方法如下:[/mnt/yaffs]cd/dev[/dev]ln–sf/dev/tts/0ttyS0打开串口是通过标准的文件打开函数来实现的intfd;fd=open("/dev/ttyS0",O_RDWR);/*以读写方式打开串口*/if(-1==fd){/*不能打开串口一*/ perror("提示错误!");}串口设置最基本的设置串口包括波特率设置,效验位和停止位设置。串口的设置主要是设置structtermios结构体的各成员值,关于该结构体的定义可以查看/arm2410s/kernel-2410s/include/asm/termios.h文件。structtermio{ unsignedshortc_iflag; /*输入模式标志*/ unsignedshortc_oflag; /*输出模式标志*/ unsignedshortc_cflag; /*控制模式标志*/ unsignedshortc_lflag; /*localmodeflags*/ unsignedcharc_line; /*linediscipline*/ unsignedcharc_cc[NCC];/*controlcharacters*/};设置这个结构体很复杂,可以参考man手册或者由赵克佳、沈志宇编写的《UNIX程序编写教程》,我这里就只

温馨提示

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

评论

0/150

提交评论