Unix程序设计基础

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

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

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

资源描述

Unix程序设计基础谢翰天网实验室《汇编语言程序设计》助教理科一号楼1220,Email:e@pku.edu.cnUnix程序设计基础因为我们是在Linux环境下编写汇编程序,所以必须了解一些Unix/Linux的编程原理和方法。主要是了解Linux的系统调用。Linux编程比windowsAPI编程简单的多,很好学。80386CPU简介Intel80386是一个具有时代意义的产品,是80x86家族的第一个32位处理器。迄今为止Intel家用CPU都沿用80386的体系结构。它有以下特征:80386CPU特征1、两种运行模式:在实模式下,它相当于一个快速的8086CPU。16位地址总线和16位数据总线。由于每个地址分两次发送,实际的寻址能力为220=1M。具体寻址方法在以后的课程里介绍。80386CPU特征在保护模式下,80386才能发挥出真正的性能。32位地址总线和32位数据总线,寻址能力为232=4G。在机器启动时,CPU处于实模式,必须通过模式切换才能进入保护模式。具体方法很烦,可能不在课程的范围内。有兴趣的同学可参考Linux内核的引导和启动部分源代码。80386CPU特征Linux,windows等现代操作系统都是运行在保护模式下。为了兼容16位程序,80386还提供了v86模式。如在windows下运行DOS程序,就实在v86模式下。80386CPU特征2、四种特权级别在实模式下,没有级别之分。在保护模式下,CPU有4各特权级别。特权级0,特权级1,特权级2,特权级3。Linux只使用了0和3,分别称为内核态和用户态。在内核态下,CPU可执行任何指令,在用户态下CPU只能执行非特权指令。80386CPU特征当CPU处于内核态,可以随意进入用户态;而当CPU处于用户态,只能通过中断的方式进入内核态。一般程序一开始都是运行于用户态,当程序需要使用系统资源时,就必须通过调用软中断进入内核态,这个软中断就称为系统调用(systemcall),在Linux下为int80h。80386CPU特征由于每一次的中断调用都涉及很多的寄存器操作,为了方便,一般操作系统都系统调用封装成一组C函数,这些函数所作的操作就是设置寄存器值,调中断,并把结果返回。Linux下文件/usr/include/sys/syscall.h列出了所用的系统调用函数,而实际上是定义在/usr/include/asm/unistd.h中。80386CPU特征3、分段式与分页式结合80386使用段选择子与段内地址来产生一个虚拟地址,如果使用了分页方式,则在通过页面映射产生一个物理地址;如果没有使用分页方式,这个虚拟地址就是物理地址。Linux将所用的段起始地址定位0,因此,Linux并没有使用80386的分段功能。每个进程的虚拟地址都是从0x0至0xffffffff。Unix文件描述字对于Unix而言,所有对设备和文件的操作都使用文件描述字进行的。文件描述字是一个非负整数,下面的例子是打开文件并文件开头写入一个字符串。Unix文件描述字首先打开文件:intfd;char*str=“Hello,Linux”;if((fd=open(“./test.txt”,O_WRONLY|O_CREAT,0644))0){perror(“open”);exit(1);}Unix文件描述字写入数据:if(write(fd,str,strlen(str))0){perror(“write”);exit(1);}关闭文件描述符:close(fd);Unix文件描述字在上面的代码中,open,write,close几个函数是系统调用,而perror,exit这是普通的库函数。大多数系统调用返回负数表示失败,如open和write,在这里我们当它失败是打印错误信息(perror)并结束程序(exit)。作为一种好的编程风格,不要在除了main函数以外的任何函数里调用exit。Unix文件描述字在上例中,如果把open的一个参数换成”/dev/fd0”,那么程序的功能就是在软盘的0磁道0扇区写入”Hello,Linux”。在Linux下,一切设备都是文件,都是通过文件描述字来访问。下面介绍一些常用的系统调用。常用的系统调用1、文件操作2、进程控制3、信号处理4、高级I/O5、IPC6、网络通信…除特殊说明,所有函数返回负值表示失败。文件操作打开文件open,创建文件creat函数原型:#includesys/types.h#includesys/stat.h#includefcntl.hintopen(constchar*filename,intflags,mode_tmode);intcreat(constchar*filename,mode_tmode);文件操作open与creat的第一个参数filename为要打开或创建的文件名。open第二个参数flags。可以是O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_CREAT,O_EXCL,O_TRUNC,O_NOCITY,O_NONBLOCK,O_SYNC的任意”|”结果。如:O_RDWR|O_APPEND|O_CREAT文件操作常见的flags常数:O_RDONLY:只读O_WRONLY:只写O_RDWR:读写O_APPEND:追加O_CREAT:不存在文件的话创建新文件O_EXCL:如果文件存在则失败O_TRUNC:如果文件存在这则截断文件O_NONBLOCK:非阻塞IO。以后讲文件操作open和creat的最后一个参数mode指明创建文件的的访问权限。对于open而言,只有当flags中包含O_CREAT时mode参数才有效。creat(filename,mode);等价于:open(filename,O_WRONLY|O_CREAT|O_TRUNC,mode);文件的访问权限当用户企图访问一个文件,他/她要么是文件所有者,要么是文件组成员,要么是其他用户;访问的方式可能是读,写,或执行。UNIX文件访问权限的低9每一位表示一种访问是否许可。如111101001:高三位111,表示文件所有者对文件可读,可写,可执行;中间三位101:表示文件对同组成员可读,可执行;第三位001表示其他用户对文件可执行。前面例子中,open的mode为0644,对应二进制110100100,表示文件所有者对文件可读可写,其他人对文件只读。文件操作open与creat会打开的文件描述字。当文件使用完毕,需调用close关闭文件。close的原型如下:#includeunistd.hintclose(intfiledes);其中filedes为open或creat返回的文件描述字。文件操作读文件read与写文件write函数原型:#includeunistd.hssize_tread(intfiledes,void*buff,size_tnbytes);ssize_twrite(intfiledes,void*buff,size_tnbytes);文件操作filedes:已打开的文件描述字buff:在read中为读出的数据存放的缓冲区;在write中为要写入的数据区。nbytes:读出或写入的字节数。read和write返回成功读出的字节数。文件操作设置文件读写位置lseek函数原型:#includesys/types.h#includeunistd.hoff_tlseek(intfiledes,off_toffset,intwhence);参数whence指明offset是相对文件开始、文件尾还是当前位置,它可以是SEEK_SET,SEEK_CUR或SEEK_END之一。文件操作例如,把文件读写位置设置到文件尾:lseek(fd,0,SEEK_END);把文件读写位置设置到当前位置之前3个字节:lseek(fd,-3,SEEK_CUR);文件操作对比标准IO:fopen,fclose,fread,fwrite,fseek。标准IO的文件handler为FILE*型,底层IO为int型。标准IO有很好的缓冲机制,并且提供了更多方便操作的函数。因此,读写普通文件最好使用标准IO。但有些场合只能使用底层IO。如网络通信,多路IO。

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

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

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

×
保存成功