02-Linux系统编程-00_系统调用与标准IO

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

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

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

资源描述

嵌入式系统工程师2系统调用与标准I/O库33系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲44系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲55类UNIX系统的软件层次系统调用与内核66系统调用是操作系统提供给用户程序的一组“特殊”接口。Linux的不同版本提供了两三百个系统调用。用户程序可以通过这组接口获得操作系统(内核)提供的服务。例如:用户可以通过文件系统相关的系统调用,请求系统打开文件、关闭文件或读写文件。系统调用概述77系统调用概述88系统调用按照功能逻辑大致可分为:进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控制、用户管理。系统调用通常通过函数进行调用。系统调用的返回值:通常,用一个负的返回值来表明错误,返回一个0值表明成功。错误信息存放在全局变量errno中,用户可用perror函数打印出错信息。系统调用概述99系统调用遵循的规范在Linux中,应用程序编程接口(API)遵循POSIX标准。POSIX标准描述了操作系统的函数接口规范(函数名、返回值、参数等)。不同操作系统下编写的程序只要遵循POSIX标准,程序都可以直接移植。如:linux下写的open、write、read可以直接移植到unix操作系统下。系统调用概述1010系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲1111系统调用中操作I/O的函数,都是针对文件描述符的。通过文件描述符可以直接对相应的文件进行操作。如:open、close、write、read、ioctl文件描述符文件描述符是非负整数。打开现存文件或新建文件时,系统(内核)会返回一个文件描述符。文件描述符用来指定已打开的文件。#defineSTDIN_FILENO0//标准输入的文件描述符#defineSTDOUT_FILENO1//标准输出的文件描述符#defineSTDERR_FILENO2//标准错误的文件描述符程序运行起来后这三个文件描述符是默认打开的。系统调用I/O函数1212open函数:打开一个文件#includesys/types.h#includesys/stat.h#includefcntl.hintopen(constchar*pathname,intflags);或intopen(constchar*pathname,intflags,mode_tmode);系统调用I/O函数1313open函数:打开一个文件参数:pathname:文件的路径及文件名。flags:open函数的行为标志。mode:文件权限(可读、可写、可执行)的设置。返回值:成功返回打开的文件描述符。失败返回-1,可以利用perror去查看原因系统调用I/O函数1414系统调用I/O函数flags的取值及其含义取值含义O_RDONLY以只读的方式打开O_WRONLY以只写的方式打开O_RDWR以可读、可写的方式打开O_CREAT文件不存在则创建文件,使用此选项时需使用mode说明文件的权限O_EXCL如果同时指定了O_CREAT,且文件已经存在,则出错O_TRUNC如果文件存在,且为只读或只写的方式打开,则清空文件内容O_APPEND写文件时,数据添加到文件末尾O_NONBLOCK当打开的文件是FIFO、字符文件、块文件时,此选项为阻塞标志位1515系统调用I/O函数mode的取值及其含义取值八进制数含义S_IRWXU00700文件所有者的读、写、可执行权限S_IRUSR00400文件所有者的读权限S_IWUSR00200文件所有者的写权限S_IXUSR00100文件所有者的可执行权限S_IRWXG00070文件所有者同组用户的读、写、可执行权限S_IRGRP00040文件所有者同组用户的读权限S_IWGRP00020文件所有者同组用户的写权限S_IXGRP00010文件所有者同组用户的可执行权限S_IRWXO00007其他组用户的读、写、可执行权限S_IROTH00004其他组用户的读权限S_IWOTH00002其他组用户的写权限S_IXOTH00001其他组用户的可执行权限1616close函数:关闭一个文件#includeunistd.hintclose(intfd);参数:fd是调用open打开文件返回的文件描述符返回值:成功返回0。失败返回-1,可以利用perror去查看原因系统调用I/O函数1717write函数:把指定数目的数据写到文件#includeunistd.hssize_twrite(intfd,constvoid*addr,size_tcount);参数:fd:文件描述符。addr:数据首地址。count:写入数据的字节个数。返回值:成功返回实际写入数据的字节个数。失败返回-1,可以利用perror去查看原因。系统调用I/O函数1818read函数:把指定数目的数据读到内存#includeunistd.hssize_tread(intfd,void*addr,size_tcount);参数:fd:文件描述符。addr:内存首地址。count:读取的字节个数。返回值:成功返回实际读取到的字节个数。失败返回-1,可以利用perror去查看原因。系统调用I/O函数1919练习1目标:使用系统调用实现cp命令。原理:使用系统调用open打开文件,使用read从文件读数据,使用write向文件写数据。传给可执行程序的参数个数存放在mian函数的argc中,参数首地址存放在指针数组argv中。标准I/O库函数2020练习2目标:使用系统调用实现who命令。who命令用来显示登陆系统的用户。第一列显示用户名;第二列显示终端名;第三列显示登陆时间。$who系统调用I/O函数2121原理提示:用户登陆信息放在/var/run/utmp文件中,who通过读取该文件获取登陆信息。utmp这个文件里保存的是结构体数组,数组元素是utmp类型的结构体。utmp结构体类型的定义路径:/usr/include/i386-linux-gnu/bits/utmp.h系统调用I/O函数2222编程提示:只读方式打开/var/run/utmp文件。循环调用(read)读取数据,直到读完utmp文件。/var/run/utmp文件中除存有用户登陆的信息还存有其它信息。可每次读完数据后判断结构体的成员ut_type的值,当ut_type的值为USER_PROCESS时,结构体里的信息才为用户登陆的信息。打印登陆用户名(ut_user)、终端名(ut_line)、登陆时间(ut_tv.tv_sec)。打印时间的时候用ctime函数去转换。系统调用I/O函数2323系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲2424为了更好地保护了内核,在Linux中,把程序运行空间分为内核空间和用户空间,它们分别运行在不同的级别上。用户进程在通常情况下不允许访问内核数据,也无法使用内核函数。但在有些情况下,用户空间的进程需要获得一定的系统服务,这时,就必须通过系统调用。系统调用与内核2525系统调用与内核2626应用程序运行在用户空间,系统调用需要切换到内核空间,应用程序应该以某种方式通知内核需要切换到内核空间。通知内核的机制是靠软件中断实现的:应用程序执行异常指令,引发一个异常,程序进入中断,系统切换到内核态去执行异常处理程序。此处的异常处理程序即系统调用处理程序syscall()。所有的系统调用陷入内核的方式都一样,所以仅仅是陷入内核空间是不够的。必须以某种方式通知内核进入异常的原因。系统调用与内核2727Unix系统通过系统调用号通知内核进入异常的原因。系统调用号操作系统给每个系统调用分配了一个唯一的编号,这个编号就是系统调用号。用户空间进程执行一个系统调用时,这个系统调用号就被用来指明执行哪个系统调用。系统调用号相当关键,一旦分配就不能再有任何变更,否则编译好的应用程序会崩溃。此外,如果一个系统调用被删除,它所占用的系统调用号也不允许被回收利用。路径:/usr/include/i386-linux-gnu/asm/unistd_32.h系统调用概述2828在x86平台上,这个传递动作是通过在触发软中断前把系统调用号装入寄存器eax实现的。这样系统调用处理程序一旦运行,就可以从eax中得到数据。除了系统调用号外,大部分系统调用还需要一些外部的参数输入。故,在发生异常的时候,应该把这些参数从用户空间传给内核。系统像传递系统调用号一样,把这些参数也放在寄存器中。在x86系统上,ebx、ecx、edx、esi和edi按顺序存放前5个参数。若有6个或更多参数,应该用一个单独的寄存器存放这些参数在用户空间的地址。给用户空间的返回值也可以通过寄存器传递,在x86系统上,它存放在eax寄存器中。系统调用与内核2929系统调用与内核3030系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲3131库函数由两类函数组成不需要调用系统调用不需要切换到内核空间即可完成函数全部功能,并且将结果反馈给应用程序,如strcpy、bzero等字符串操作函数。需要调用系统调用需要切换到内核空间,这类函数通过封装系统调用去实现相应功能,如printf、fread等。系统调用与库3232系统调用与库库函数与系统调用的关系:并不是所有的系统调用都被封装成了库函数,系统提供的很多功能都必须通过系统调用才能实现。3333系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效率。当运行内核代码时,CPU工作在内核态,在系统调用发生前需要保存用户态的栈和内存环境,然后转入系统态工作。系统调用结束后,又要切换回用户态。这种环境的切换会消耗掉许多时间。库函数访问文件的时候根据需要,设置不同类型的缓冲区,从而减少了直接调用IO系统调用的次数,提高了访问效率。系统调用与库3434系统调用与库应用程序调用printf函数时,函数执行的过程:3535系统调用概述系统调用I/O函数系统调用与内核系统调用与库标准I/O库函数大纲3636无论是编写系统程序还是应用程序,都离不开I/O这个重要的环节。相对于低级的I/O操作(即系统调用级的I/O),标准I/O库函数处理了很多细节,如缓存分配等。考虑到代码的可移植性,开发人员应该在编写代码时尽可能使用标准库函数。标准I/O库函数3737I/O的管理分类由ANSI标准提供的标准IO库函数几乎被所有的操作系统支持,如winsdows下编写的程序几乎不用做任何修改就可以在linux下重新编译运行。如:fopen、fread、fwrite、fclose。以系统调用的方式给用户提供函数接口(遵循POSIX标准)例如linux操作系统提供的文件IO接口。如:open、close、read、write、ioctl。系统调用与操作系统直接相关,直接使用系统调用编写的程序的可移植性差。标准I/O库函数3838头文件stdio.h中声明了标准C的I/O库,标准C的I/O库在所有通用计算机上的C语言实现都是相同的。对于标准I/O操作函数来说,打开或创建一个文件的时候,会返回一个指向FILE结构体的指针。FILE结构体包含了I/O函数库为管理文件所需要的尽可能多的信息。包括了用于I/O文件的文件描述符、指向流缓存的指针、缓存长度等。定义路径:/usr/include/libio.h别名(typedef):/usr/include/stdio.h标准I/O库函数3939打开流头文件:#includestdio.h定义函数:FILE*fopen(constchar*pathname,constchar*mode);函数说明:pathname:文件的路

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

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

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

×
保存成功