版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux程序设计教程Linux程序设计教程第1章Linux基础2第1章Linux基础1.1Unix/Linux简介1.2库函数与系统调用1.3Linux常用命令1.4案例1:通过SSH终端登录Linux21.1Unix/Linux简介Unix概述1969年:KenThompson汇编语言1973年:与DennisRitchie用C语言重写UNIXⅢUNIX分为SystemV和BSD两大主流1978年:加利福尼亚大学伯克利分校以UNIX第六版为基础改进成BSD系列UNIX1983年:SystemV版本1发布,第一个商业UNIX版本SystemV版本4是较成功的,或称为SVR41992年,版权纠纷,伯克利分校删除原UNIX代码,重写内核,1994年诞生4.4BSD版本,成为现代BSD基本版本21.1Unix/Linux简介Linux概述1987年:荷兰的Vrije大学的AndrewS.Tanenbaum开发MINIX,用于操作系统课程的教学。1991年:Linus学习MINIX,并发布了Linux内核。2003年:Linux2.6版本内核发布Linux版本的两种说法内核版本:Linux2.4.20,Linux2.6等r.x.y:r-主版本号,x-偶数稳定奇数开发,y-错误修补次数发行版本:RedHatLinux9.0,SUSE10,Ubuntu等厂家将Linux内核与外围实用程序和文档包装,提供安装界面和系统配置、管理工具等,形成的操作21.2库函数与系统调用系统调用操作系统提供给外部程序的接口。库函数C语言库函数提供给C语言编程需要的功能,有的库函数需要调用系统调用接口。Linux中有GNU的glibc,POSIX的线程函数库等。从用户角度观察都以常见的C语言函数形式出现,调用方法一致。从实现者角度观察调用库函数有的需要内核的服务,有的不需要,需要内核服务的库函数是要调用系统调用的。------用户态调用系统调用后执行内核程序。------核心态1.3Linux常用命令用户和用户组useraddpasswduserdelgroupaddgroupdel71.3Linux常用命令文件和目录mkdirmvcprmchgrpchown81.3Linux常用命令进程pskill获取帮助信息man9案例1:通过SSH终端登录Linux分析及设计本项目要求在Windows中远程访问虚拟机中的Linux系统,使用命令创建本书中所需的各章节目录,然后将这些目录下载到Windows的某个文件夹中。如果在一个局域网中有两台以上的计算机,则可以取其中一台安装任意发行版本的Linux系统作为服务器,其他计算机作为客户机端,可以安装Windows或Linux系统。如果只有一台计算机,则可以考虑在当前的操作系统中安装一个虚拟机,在虚拟机中安装Linux作为服务器。虚拟机软件可以考虑使用VMware。以当前的操作系统作为客户端机对服务器进行登录访问。10案例1:通过SSH终端登录Linux见教材。11谢谢!Linux程序设计教程第2章Linux系统开发环境14第2章Linux下项目开发环境2.1Vi编辑器2.2GCC编译器2.3
Makefile文件的使用2.4
GDB调试器2.5
库2.6
案例2:简易学生成绩计算152.1Vi编辑器vi的工作模式vi的基本用法vi的高级用法162.1Vi编辑器vi三种模式插入模式:键盘按键被当作文本命令模式:键盘按键被当作命令底行模式:输入“:”“?”“/”后进入,完成某些功能。172.1Vi编辑器vi的基本用法启动命令提示符后输入“vi文件名”以下所说的vi的用法都是在命令模式下,所以在插入模式时要先Esc退出编辑状态。保存不退出:w另存为:w新文件名退出:wq保存并退出:q!不保存退出182.1Vi编辑器vi的高级用法文本操作复制yyywnyynyw剪切dddwnddndw粘贴
pP192.1Vi编辑器vi的高级用法行数跳转到某行数字G底行模式,setnu显示行号setnonu取消显示行号撤销u重做
.(句点)搜索
/?202.2
GCC编译器GCC编译器介绍功能强大的编译器,源代码到可执行文件有4个步骤:处理头文件和预编译语句,生成.i文件生成.s汇编代码文件将编译阶段生成的.s文件转换成目标文件.o将目标文件和所用的库函数连接到可执行文件中适当位置,生成可执行文件源代码.ccppcc1asld预处理编译汇编连接212.2
GCC编译器GCC的基本用法基本格式:gcc[选项][源文件名,如ex1.c]生成可执行文件gcc-o可执行文件名源文件名或gcc源文件名-o可执行文件名要用GDB工具调试最后加上-g选项显示附加的警告信息最后加上-Wall选项222.3
Makefile文件的使用make对于大型的开发项目来说,可能包括很多源文件,使用make和makefile文件可以清晰地理顺各个源文件之间的关系。。make主要是通过make命令调用makefile文件,通过makefile文件描述源程序之间的相互依赖关系,并自动维护编译工作。调用格式“make目标”,查找makefile文件中指定的目标一般都省略目标直接用make来查找makefile文件中的第一个目标。232.3
Makefile文件的使用makefile文件内容显式规则隐含规则变量定义指示符注释:#后为注释,行注释242.3
Makefile文件的使用显式规则格式:目标:依赖
[tab]命令注意:[tab]位置按键盘上的tab键举例如果hello不存在则进行编译。如果hello日期没有hello.c日期新则进行编译。hello:hello.c gcc–ohellohello.c252.3
Makefile文件的使用变量类似C语言的宏,大小写敏感(推荐大小写搭配名字)$<,$@.$^等都是自动化变量$@目标文件$^所有依赖文件声明时赋初值,使用时变量名前加$,最好用()将名字括起。如:OBJ=test.ofun1.ofun2.otest:$(OBJ) gcc–o$@$^262.3
Makefile文件的使用make执行过程当前目录下按照GNUmakefile、makefile、Makefile的顺序查找makefile文件查找文件中的第一个目标文件如edit。若edit不存在,edit后依赖的文件都存在,并且edit修改时间比依赖文件的时间早,则会执行命令。若edit依赖的.o文件不存在,则在当前文件中查找目标为依赖文件的规则,生成.o文件。通常clean伪目标是用来清除中间文件的,而不是要生成clean文件。一般的makefile文件都加入clean。272.4
GDB调试器错误分类编译错误:gcc时出现错误根据错误提示找到错误,从第一个错误开始找。到网上搜索错误提示总结编译错误的解决方法运行错误:gcc正确,运行时出现错误调试器:GDB打印调试在程序适当位置加printf提示语句(记得printf中加\n)在调用函数后根据函数返回值结合perror查找错误282.4
GDB调试器GDB工具GNU的调试器(debugger),字符模式。设置断点监视变量值单步执行修改变量的值292.5
库库的概念库函数,由系统提供的,供程序员开发时调用的,完成特定功能的函数。如printf等,一般是.o目标代码。便于编程隐藏细节,降低开发难度和开发周期商业软件,保护知识产权存放函数的文件就像存放函数的仓库,如Glibc库,提供了系统调用和C库的基本函数。Linux下库的形式:静态库、共享库。302.5
库静态库一般以.a结尾,libtest.a编译时:库函数被合并在可执行文件中执行时:提供可执行文件即可可执行文件会变大,适合于小程序调用共享库一般以.so或.so.x结尾,x代表版本,如libtest.so.1编译时:库文件不被合并入可执行文件执行时:提供可执行文件和库文件才能执行可执行文件会比较小,并且几个可执行文件可以共享库,适合于大型项目。312.5
库静态库的创建与使用创建gcc-clibhello.c生成目标文件libhello.oarrclibhello.alibhello.o生成静态库libhello.a使用在usehello.c中调用库函数print_hellogcc-ousehello_staticusehello.clibhello.a生成的可执行文件usehello_static,可以直接运行。322.5
库共享库的创建与使用创建gcc–fPIC-clibhello.c生成目标文件libhello.ogcc-shared-olibhello.solibhello.o生成共享库libhello.so使用共享库默认搜索路径是/usr/lib或/lib,拷贝过去
cplibhello.so/usr/lib使用动态链接库gcc-ousehello_dynamicusehello.c–lhello或者不拷贝直接使用以下命令编译gcc-ousehello_dynamicusehello.c–L./–lhello332.5
库共享库的创建与使用创建gcc–fPIC-clibhello.c生成目标文件libhello.ogcc-shared-olibhello.solibhello.o生成共享库libhello.so使用共享库默认搜索路径是/usr/lib或/lib,拷贝过去
cplibhello.so/usr/lib使用动态链接库gcc-ousehello_dynamicusehello.c–lhello或者不拷贝直接使用以下命令编译gcc-ousehello_dynamicusehello.c–L./–lhello342.6案例2:简易学生成绩计算分析与设计本项目完成一个简易的学生成绩计算功能:从键盘输入N个学生的姓名,年龄,数学成绩,语文成绩四项信息,输入完N个学生信息后,计算各个学生的总成绩和平均成绩,计算完毕后输出每个学生的姓名、年龄、数学成绩、语文成绩、总成绩、平均成绩。要求将输入、计算、输出三个过程分别使用独立函数实现,三个函数分别保存在三个不同的源文件中。352.6案例2:简易学生成绩计算见教材。谢谢!Linux程序设计教程第3章Linux程序设计初步38第3章Linux程序设计初步3.1程序及进程的存储结构3.2变量的类型修饰符3.3命令行参数及获取3.4环境变量3.5时间管理3.6错误代码3.7标准I/O与文件I/O3.8案例3:设置环境变量393.1程序及进程的存储结构Linux进程结构可执行文件执行时,将演变成至少一个进程。每个进程都有自己独立的处理环境和系统资源。进程结构代码区初始化数据区未初始化数据区堆栈403.1程序及进程的存储结构Linux进程结构413.1程序及进程的存储结构Linux进程结构代码区text——加载可执行文件代码段数据区data——加载可执行文件数据段未初始化数据区bss——加载可执行文件BSS段堆——用于动态内存分配,程序员进行分配和释放栈——存放函数的参数值、返回值、局部变量等,系统自动分配释放。数据段、BSS段的变量生存周期为整个进程运行过程。局部变量生存周期为函数内部,即申请到释放该段栈空间423.2变量的类型修饰符433.2变量的类型修饰符inta=0;char*p0;intmain(void){ intb; chars[]="abc"; char*p1,*p2; char*p3="123456"; staticintc=0;
p1=(char*)malloc(10);
p2=(char*)malloc(20); free(p1); free(p2); p1=NULL; p2=NULL;}考虑:(1)变量所占内存字节数(2)变量存储位置443.3命令行参数及获取命令行参数概念在命令行输入的信息由空格或tab隔开。由于程序都从main函数开始执行,所以命令行输入的信息将被main函数接收,也称为命令行参数。如果程序不需要命令行信息,则main不需要带形参,否则需要加上形参。main原型intmain(intargc,char*argv[]);或intmain(intargc,char*argv[],char*envp[]);453.3命令行参数及获取main函数intmain(intargc,char*argv[]);argc:代表命令行中输入项的个数(包括可执行文件名)argv:数组长度为argc。argv[0]~argv[argc-1]指向命令行各输入项的字符串首地址,argv[argc]存放NULL。字符串数组指针463.4环境变量代表当前系统环境信息用户可进行查看,增加/修改,删除设置环境变量命令方式在shell中设置,仅在当前shell中有效,重启无效函数方式在程序运行过程中设置,仅在进程过程中有效。永久有效(在文件中修改)所有用户识别:/etc/profile某一用户识别:~/.bash_profile重启系统或使用“.文件名”使配置立即生效473.4环境变量命令方式查看变量setecho$varname增加或修改exportvarname=value删除:unsetvarname483.4环境变量函数方式查看变量char*getenv(constchar*var);var代表变量名,成功返回变量值,否则返回NULL。如:char*val=getenv(“PATH”);删除voidunsetenv(cosntchar*var);var代表变量名如unsetenv(“AGE”);493.4环境变量函数方式增加或修改intputenv(constchar*string);参数格式:“变量名=变量值”。如putenv(“AGE=20”);intsetenv(constchar*var,constchar*val,intoverwrite);var变量名,val变量值,overwrite(非0覆盖已存在的变量)如setenv(“AGE”,”20”,1);返回值:成功返回0,否则返回-1。503.5时间管理时间基本概念GMTGreenwichMeanTime格林尼治时间UTCUniversalTimeCoordinated国际协调时间Localtime本地时间513.5时间管理Linux下时间表示方法time_t从1970年1月1日午夜开始计数的秒数值。与系统直接进行交互的类型,UTC结构体structtm将UTC时间根据当前设置的时区进行分解年、月、月日、时、分、秒、周日、年日等。字符串:例如TueJul2309:44:172002523.5时间管理Linux下时间表示方法structtm{ inttm_sec;[0,61],2秒跳秒
inttm_min;[0,59] inttm_hour;[0,23] inttm_mday;[1,31] inttm_mon;[0,11] inttm_year;yearsince1900 inttm_wday;[0,6] inttm_yday;[0,365]inttm_isdst;夏令时标记
(>0夏令时有效,0无效,-1信息不可用)};533.5时间管理时间表示转换图time_t字符串structtmlocaltimemktimectimeasctimegetdatetime543.5时间管理time头文件:#include<time.h>功能:得到系统当前的时间,time_t原型:time_ttime(time_t*t);举例:time_tcurt;curt=time(NULL);或time_tcurt;time(&curt);553.5时间管理localtime头文件:#include<time.h>功能:把time_t转换成本地时间原型:structtm*localtime(consttime_t*t);举例:time_tcurt;time(&curt);structtm*ptm;ptm=localtime(&curt);563.5时间管理ctime头文件:#include<time.h>功能:把time_t转换成本地时间字符串原型:char*ctime(consttime_t*t);举例:time_tcurt;time(&curt);char*pstrt;pstrt=ctime(&curt);573.6错误代码errno头文件:#include<errno.h>举例:printf("errno1=%d\n",errno);if(fopen("any","r")==NULL){ printf("errno2=%d\n",errno);}583.7标准I/O与文件I/O对于文件的输入/输出一般有两种方式,一个是标准I/O,另一个是文件I/O。操作标准I/O文件I/O打开fopen,freopen,fdopenopen关闭fcloseclose读getc,fgetc,getcharfgets,getsfreadread写putc,fputc,putcharfputs,puts,fwritewrite593.7标准I/O与文件I/O标准I/O提供了3种类型的缓冲。(1)全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常由标准I/O库实施全缓冲。一个文件流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc函数获得需使用的缓冲区。603.7标准I/O与文件I/O(2)行缓冲。在这种情况下,当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。当I/O操作涉及一个终端时,通常使用行缓冲。因为标准I/O库用来收集每一行的缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使没有写一个换行符,也进行I/O操作。613.7标准I/O与文件I/O(3)无缓冲。标准I/O库不对字符进行缓冲存储。例如,如果用I/O函数fputs写15个字符到不带缓冲的文件流中,则该函数很可能用系统调用write将这些字符立即写至相关联的打开文件中。623.8案例3:设置环境变量本项目通过命令行来对进程设置某环境变量的值,如果命令行未给出值则获取当前时间作为该环境变量的值,要求显示该环境变量修改前与修改后的值。633.8案例3:设置环境变量见教材。谢谢!Linux程序设计教程第4章文件I/O66第4章文件I/O4.1文件系统简介4.2访问文件的内核数据结构4.3文件基本I/O操作4.4文件访问的同步4.5案例4:文件复制命令的实现674.1文件系统简介文件系统操作系统中管理文件的那部分软件及管理文件所需要的各种数据结构。不同的操作系统管理文件的方法各不相同,使用一个新设备时,需要“格式化”,其实就是操作系统按照自己的方式在设备上建立文件系统,操作系统对存储设备的空间进行划分,并在其上建立初始的数据结构。文件系统建立好了,OS就可以在上面存取并管理文件了。文件系统的类型:Dos、windows采用的FAT、NTFS,Linux采用的ext2、ext3,Unix采用的UFS。684.1文件系统简介VFS虚拟文件系统694.1文件系统简介VFS主要对象对象说明superblock对象表示一个具体的可封装的文件系统inode对象表示一个具体的文件dentry对象表示一个目录条目,或路径中的一个分量file对象表示一个与进程相关联的已打开的文件704.1文件系统简介索引节点(inode)Linux系统采用“按名存取”的方式访问文件。除了文件名以外,文件的主要属性信息都存放在inode节点中。目录文件中保存着文件名和索引节点的对应关系。ls-i命令。Linux系统中,每个保存在磁盘的文件包括两部分索引节点inode记录文件属性信息(ls-l)除了文件名。文件的属性包括:文件类型,访问权限,文件主人,组,长度,访问日期等等。数据块存放文件具体内容714.1文件系统简介索引节点(inode)右图为索引节点数据结构图属性数据724.1文件系统简介索引节点(inode)打开文件时系统会将磁盘上文件的i节点信息拷贝到内存VFS的对应该文件的i节点中。磁盘Ext2的i节点数据类型structext2_inode/usr/src/linux-2.4/include/linux/ext2_fs.h217行内存VFS的i节点数据类型为structinode/usr/src/linux-2.4/include/linux/fs.h435行注意:硬链接文件的inode与源文件的inode相同。734.1文件系统简介一个简单的Unix文件系统组成引导块:用于引导该分区内操作系统的引导程序超级块:UFS的重要参数,如文件系统的块、索引节点总数,空闲块、空闲索引节点数索引节点表(i节点):文件系统中索引节点的集合数据块:存储文件数据744.1文件系统简介Linux文件系统—Ext2第一个是引导块,其他空间分成各个块组每个块组中:超级块,块组描述符,数据块位图,索引节点位图,索引节点,数据块754.1文件系统简介文件类型P70普通文件(rugularfile)目录文件(directory)字符设备文件(characterdevice)块设备文件(blockdevice)FIFO文件(fifo)符号链接文件(symboliclink)socket套接字文件(socket)764.1文件系统简介文件的访问权限P71权限是多用户系统中文件管理的重要内容Linux中,用户分为三类:owern,group,other基本访问权限也分为三种:r,w,x特殊权限:setuid,setgid,sticky(暂不介绍,进程一章会讲)Linux文件的索引节点inode里面有一个st_mode字段,记录文件类型及权限。该字段共16bit,高四位表示文件类型,低12位表示文件权限。P734.1文件系统简介文件权限的表示方法字母:r读w写x执行-无,如rwxr-xr-x数字:二进制1有0无,如111101101或755宏:S_IPwww模式S_I固定,P可为R或W或X,W可为USR或GRP或OTH,用或运算如S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH编程中作为参数只能用数字或宏4.1文件系统简介794.2访问文件的内核数据结构进程结构体task_struct中有一成员structfiles_struct*files代表当前打开文件,files_struct结构体中包含当前打开文件指针,指向structfile打开文件表某项,file结构体中包含打开文件的信息以及位置,并间接指向已经拷贝入内存的文件的i节点。每打开一次文件系统增加一个file表项进程增加一个fd表项(以文件描述符为下标),通过指针指向file表项用户通过文件描述符和系统调用访问该文件。4.2访问文件的内核数据结构814.3文件基本I/O操作文件描述符用户空间中任何打开的文件都被分配一个唯一的非负整数,标识该打开文件,即文件描述符(filedescriptor)进程默认打开的三个文件描述符标准输入0标准输出1标准错误输出2选用文件描述符中未使用的最小值824.3文件基本I/O操作常用系统调用open 打开/新建文件creat 新建文件read 读文件write 写文件lseek 定位文件偏移量close 关闭文件83创建/打开文件#include<sys/stat.h>#include<fcntl.h>
intopen(constchar*path,intflags,mode_tperms);说明打开已经存在的文件,perms可省略,即:
intopen(constchar*path,intflags);创建并打开一个不存在的文件,三个参数都要写。84创建/打开文件intopen(constchar*path,intflags,mode_tperms);参数path:文件名,其他目录需要写明路径flags:打开文件的方式,用或运算perms:文件权限,仅创建时需要返回值成功返回最小可用的文件描述符,即访问当前文件所用的文件描述符。失败返回-1(置errno)85创建/打开举例以读写方式打开文件f1intfd;fd=open(“f1”,O_RDWR);if(fd==-1){perror(“open”);exit(1);}以读写方式打开文件/home/f2,文件存在则清0,不存在则创建,设置权限为用户可读可写,同组可读,其他可读。intfd;fd=open(“/home/f2”,O_RDWR|O_TRUNC|O_CREAT,0644);if(fd==-1){perror(“open”);exit(1);}86关闭文件#include<unistd.h>intclose(intfd);功能:关闭文件,释放文件描述符,使之可再利用。参数:fd,文件描述符返回值:成功返回0,否则返回-1(置errno)当一个进程终止时,内核会自动检查并回收该进程所有的文件描述符。87open/close练习编程:fd.c
进程打开文件表ptr描述字标签ptr描述字标签…………ptr描述字标签
fd0:
fd2:
fd1:
fd3:打开文件表项……i-nodeptr文件偏移量文件状态标签i-nodeptr文件偏移量文件状态标签当前文件大小inode信息当前文件大小inode信息i-node每次open文件都会返回一个文件描述符,该文件描述符指向一个新的打开文件表项。open与文件描述符89close与文件描述符通过close可以解除文件描述符指向的打开文件表项。当close一个fd时,fd所指的打开文件表项中引用计数将减1,如果减为0,则不仅释放文件描述符,还释放该打开文件表项。如果某个打开文件表项被释放,则对该文件内存i节点中的引用计数减1,如果减为0,则释放该内存i节点。90写文件#include<unistd.h>ssize_t相当于intssize_twrite(intfd,constvoid*buf,size_tnbytes);功能:将buf所指缓冲区中的nbytes个字节写入fd所指示的打开文件中。写操作从当前文件偏移量处开始执行,写完后,当前文件偏移也将改变成功写入的字节数。参数:fd:文件描述符buf:要写入文件的数据区首地址nbytes:要写入文件的数据字节个数返回值:成功返回已写字节数,失败返回-1(置errno)
91写文件举例intfd;fd=open(“f1”,O_RDWR);if(fd==-1){perror(“open”);exit(1);}write(fd,”hello”,strlen(“hello”));close(fd);92write说明open打开文件后,文件读写偏移量自动为0。若open时设置O_APPEND标志,则写之前文件位置会自动定位到文件结尾。如果数据量大的话,可以使用循环的方式分几次把数据写入文件。由于物理介质空间不足等原因将会使得write返回值小于计划要写入文件的字节个数。实际上,write并不真正把数据写入磁盘,仅仅是传递给内核缓冲区,系统会定时将内核缓冲区的数据写入磁盘。如果出现磁盘等错误的话,数据就会丢失。write等待数据写入内核缓冲区后才返回。93读文件#include<unistd.h>ssize_tread(intfd,void*buf,size_tnbytes);功能:从一打开的文件fd中,读取nbytes字节的数据放入buf中。从当前文件偏移量处开始读数据,读完后,当前文件偏移也将改变成功读出的字节个数。参数:fd:文件描述符buf:保存读取数据的缓冲区nbytes:要读取数据的字节数返回值:成功返回已读取字符数,失败返回-1(置errno)94读文件举例intfd;charbuf[100];fd=open(“f1”,O_RDWR);if(fd==-1){perror(“open”);exit(1);}read(fd,buf,sizeof(buf)-1);close(fd);95read说明read返回0表明文件到达结尾。如果希望能读完文件所有的数据,最好通过循环方式调用read,直到读到文件尾为止。有时读到的数据可能比希望读的字节少,但系统不会置错误代码,因为这不是错误(如文件已经到结尾),需要用户自己去推测问题所在。读是从内核缓冲区读,有时,要读的数据可能还在磁盘中,所以有时进程必须等待数据从磁盘拷贝到内核缓冲区。96文件偏移量--引入将f1文件以读写方式打开,先向文件写入“helloworld”,然后从文件中读出刚刚写入的内容,然后使用write函数将刚刚读出的内容打印到屏幕上。有什么问题吗?无法读出刚写入的内容原因:对一次open返回的fd对应的文件进行写操作后,当前偏移量已经移到写后的位置了,再继续读自然什么也读不出来。97文件偏移量非负整数,标识下一次读或写文件的位置。通常读写操作都从当前文件偏移量处开始。文件偏移量保存在对应的打开文件表中每open一次文件,就能得到一个新的打开文件表项,因此每次open都可以得到一个独立的文件偏移量。一个进程多次open同一个文件,由于得到不同的fd和打开文件表项,因此每次fd都拥有各自独立的文件偏移量。98文件偏移量举例fd1=open(“ex1”,O_WRONLY);fd2=open(“ex1”,O_RDONLY);fd3=open(“ex2”,O_RDWR);问题1:open后当前文件位置为0,如果向fd1中写入100个字节,接着从fd2中读出100字节,那么读出的数据会是刚刚写入的100个字节吗?问题2:如果向fd3中写入100个字节,接着再从fd3中读出100字节,能读出刚刚写入的100个字节吗?若要设置读写偏移量,需要使用lseek系统调用函数99文件定位函数#include<unistd.h>off_tlseek(intfd,off_tpos,intwhence);参数fd:文件描述符whence:取下面其中一个值SEEK_SET:代表文件开始,即设为posSEEK_CUR:代表当前位置,即设为当前值+posSEEK_END:代表文件结尾,即设为文件长度+pospos:可正、负、0,代表相对whence的偏移值。返回值成功返回设置后的当前文件偏移量,off_t相当于long。失败返回-1(置errno)100文件定位函数举例lseek常用的几种方式设置文件的某个绝对位置
lseek(fd,值,SEEK_SET);查找文件偏移量的当前位置
off_twherewhere=lseek(fd,0,SEEK_CUR);查找文件结尾
off_twherewhere=lseek(fd,0,SEEK_END);101lseek说明内核大部分定位偏移量时是隐含的,不显式调用lseekopen:定位到第1个字节read、write:将文件偏移量增加读或写的字节数用O_APPEND标志打开文件时,每次写之前将偏移量定位到结尾。通常文件偏移量返回非负整数,甚至可能比文件大若文件偏移量位于或超过结尾时,read会返回0(代表文件结尾)如果文件偏移量比文件长度大,则下一次write操作时自动将文件长度延长到需要的大小,并将中间的字节填充为0(NULL)。102lseek练习编程:rw.c向文件写入“helloworld”,然后再读出并显示到屏幕上。103ANSIPOSIX写文件时,进程将数据复制到内核缓存,缓存未满则不将缓存排入输出队列,而是等满或者需要时才排入输出队列,然后等到达队首时才执行写操作,即延迟写。磁盘文件内核缓冲区用户缓冲区进程磁盘文件内核缓冲区进程4.4文件访问的同步104同步内核缓冲区为保证磁盘上的文件与内核缓冲区中内容一致,可以使用sync、fsync、fdatasync更新内核缓冲区,即将缓冲区内的数据写入磁盘。105sync/fsync/fdatasync#include<unistd.h>voidsync(void);将缓存所有数据排入输出队列,不等写入磁盘结束立即返回。intfsync(intfd);对内核缓存中fd指定文件进行刷新,等待写入结束才返回。成功返回0,否则返回-1intfdatasync(intfd);对内核缓存中fd文件的数据部分进行刷新,不包括文件属性,等待写入结束才返回。成功返回0,否则返回-1其他系统调用#include<unistd.h>inttruncate(constchar*path,off_tlength);intftruncate(intfd,off_tlength);功能:
truncate:通过路径截短或加长文件
ftruncate:通过文件描述符截短或加长文件参数:
path:文件路径
fd:文件描述符
length:需要截短后的长度返回值:成功返回0,否则返回-1(置错误代码)其他系统调用truncate系统调用说明如果该文件以前的长度大于length,则超过length以外的数据就不再能存取。如果以前的长度短于length,则其后果与系统有关。如果某个实现的处理是扩展该文件,则在以前的文件尾端和新的文件尾端之间的数据将读作0(也就是在文件中创建了一个空洞)。open标志O_TRUNC是truncate的一个特例,用来将一个文件的长度截短为0。其他系统调用umask系统调用#include<sys/stat.h>#include<sys/types.h>mode_tumask(mode_tcmask);功能:设置和得到文件模式的创建屏蔽字参数:cmask:新的屏蔽字返回值:旧的屏蔽字,不会返回错误。每个进程有一个文件模式的屏蔽字,当进程调用umask设置新的屏蔽字,将用新屏蔽字设置新建文件或目录的权限,直到进程结束或再次调用umask来设置其他屏蔽字。其他系统调用文件权限相关概念S_Ipwww(p代表权限,www代表用户)9中存取权限新建文件或目录权限使用系统调用:=系统调用中权限&屏蔽字反码使用命令:
文件:=666&屏蔽字反码
目录:=777&屏蔽字反码命令umask可以查看或设置屏蔽字1104.5案例4:文件复制命令的实现在UNIX中,基本文件的访问过程分为如下步骤:(1)打开文件/创建新文件。(2)访问文件(包括定位读写指针、读文件、写文件等操作)。(3)最后关闭文件。打开/创建文件使用系统调用open()/creat();访问文件的操作包括读文件read()、写文件write()、定位文件读写指针lseek()等;关闭文件使用系统调用close()。“文件复制命令的实现”项目将通过打开源文件、创建目标文件、从源文件中读出数据写入目标文件、关闭源目标文件这样的过程实现文件的复制,这将用到上述的系统调用。1114.5案例4:文件复制命令的实现见教材。谢谢!Linux程序设计教程第5章文件属性114第5章文件属性5.1获取文件属性5.2用户/组ID与名字的转换5.3硬链接与符号链接5.4dup/dup25.5文件属性的修改5.6案例5:显示文件长格式信息1155.1获取文件属性文件属性磁盘上的文件包括i节点(structext2_inode)和数据块两部分。打开文件时创建内存中的i节点(structinode),从磁盘i节点拷贝信息。i节点中保存文件的属性信息,不包括文件名。文件名和i节点号对应关系保存在文件所在目录文件中。常见的文件属性数据类型为structstat,可使用stat系列函数获取。/usr/include/bits/stat.h定义了structstat类型。structstatstructstat{ dev_t st_dev; //文件所在的设备ID
ino_t st_ino; //i节点号
mode_t st_mode; //类型权限
nlink_t st_nlink; //硬链接个数
uid_t st_uid; //uid gid_t st_gid; //gid dev_t st_rdev; //若是特殊文件,设备ID
off_t st_size; //文件大小(字节数)
time_t st_atime; //上次访问时间
time_t st_mtime; //上次修改内容时间
time_t st_ctime; //上次文件信息修改时间
blksize_t st_blksize; //块大小(字节)
blkcnt_t st_blocks; //文件块个数
};stat、fstat、lstat函数获得文件属性。#include<sys/stat.h>intlstat(cosntchar*path,structstat*buf);重点
intstat(constchar*path,structstat*buf);intfstat(intfd,structstat*buf);功能:获取文件属性stat:通过文件路径获取fstat:通过文件描述符获取lstat:通过文件路径获取,若查询符号链接文件,仅查其本身属性而不是所链接文件属性。参数:path:文件路径fd:文件描述符buf:返回的文件属性(结构体)返回值:成功返回0,否则返回-1(置errno)lstat举例获取/etc/passwd属性structstatbuf;intrt;rt=lstat(“/etc/passwd”,&buf);if(rt==-1) perror(“lstat”);Linux文件类型及权限Linux文件类型七种文件类型的二进制表达S_IFMT 0170000 文件类型的二进制掩码S_IFREG 0100000 常规文件-S_IFDIR 0040000 目录文件dS_IFBLK 0060000 块设备文件bS_IFCHR 0020000 字符设备文件cS_IFIFO 0010000 管道文件pS_IFSOCK 0140000 套接字文件sS_IFLNK 0120000 符号链接文件l文件类型检测判断某个文件的类型方法二:使用lstat获取文件属性structstat,对成员st_mode通过位操作以及文件类型宏进行判断。方法一:使用lstat获取文件属性structstat,对成员st_mode调用一系列宏进行判断。判断文件类型——方法一----test1.cstructstatbuf;lstat(“filename”,&buf);判断buf.st_mode&S_IFMT的值是否与各个文件类型宏相等,相等即为某类型。switch(buf.st_mode&S_IFMT){ caseS_IFDIR:printf("d");break; caseS_IFLNK:printf("l");break; caseS_IFREG:printf("-");break; default:printf("?");}判断文件类型——方法二structstatbuf;lstat(“filename”,&buf);宏操作返回真代表是该类型文件。S_ISREG(buf.st_mode)常规文件S_ISDIR(buf.st_mode)目录文件S_ISCHR(buf.st_mode)字符设备文件S_ISBLK(buf.st_mode)块设备文件S_ISFIFO(buf.st_mode)管道文件S_ISLNK(buf.st_mode)符号链接文件S_ISSOCK(buf.st_mode)套接字文件文件访问权限三组用户九种访问权限S_IRUSRS_IWUSRS_IXUSRS_IRGRPS_IWGRPS_IXGRPS_IROTHS_IWOTHS_IXOTH文件访问权限判断根据st_mode低9位进行判断,如st_mode&S_IRUSR:非0用户可读,0用户不可读格式:st_mode&S_Ipwww:非0www可p,0www不可p1265.2用户/组ID与名字的转换获取用户ID和用户组ID后得到的是数字,有时需要获取对应的用户名或组名等信息。用户信息保存在/etc/passwd中,组信息保存在/etc/group中1275.2用户/组ID与名字的转换通过用户ID得到用户信息#include<pwd.h>structpasswd*getpwuid(uid_tuid);通过用户组ID得到用户组信息#include<grp.h>structgroup*getgrgid(gid_tgid);1285.2用户/组ID与名字的转换通过用户ID得到用户信息#include<pwd.h>structpasswd*getpwuid(uid_tuid);返回值:成功返passwd结构体指针,否则返NULL(置errno)structpasswd{char*pw_name;//用户名
char*pw_passwd;//用户密码
uid_tpw_uid;//用户IDgid_tpw_gid;//用户所在组IDchar*pw_gecos;//真实名字
char*pw_dir;//用户主目录
char*pw_shell//用户所用Shell};1295.2用户/组ID与名字的转换通过用户组ID得到用户组信息#include<grp.h>structgroup*getgrgid(gid_tgid);返回值:成功返回结构体指针,否则返回NULL(置errno)structgroup{char*gr_name;//组名
char*gr_passwd;//组密码
gid_tgr_gid;//组IDchar**gr_mem;//组成员列表};1305.3硬链接与符号链接链接文件每个文件都有一个i节点与之对应,一个i节点可以对应一个或多个文件名。与i节点连接的文件名的个数就是文件的链接数,也即硬链接个数链接文件就是指向另一个已存文件的链接两种连接文件:硬链接文件符号链接文件1315.3硬链接与符号链接区别命令是否新增文件删除原文件/目录删除链接文件是否跨文件系统1325.3硬链接与符号链接硬链接创建 #include<unistd.h>intlink(char*pathname1,char*pathname2);参数:pathname1表示已存在文件pthname2表示硬链接文件返回值:成功返回0,失败返回-1(置errno)删除:可以删除任何文件,不专指删硬链接intunlink(char*pathname);参数:pathname要删除的链接文件名返回值:成功返回0,失败返回-1(置errno)注意:删除文件时如果已经打开则要延迟到文件关闭后才真正删除1335.3硬链接与符号链接符号链接创建#include<unistd.h>intsymlink(char*actualpath,char*sympath);参数:actualpath表示真实存在的文件或目录sympath表示符号链接文件返回值:成功返回0,失败返回-1(置errno)读取符号链接所指原文件名intreadlink(char*pathname,char*buf,intbufsize);参数pathname:符号链接文件名buf:存放被链接文件名的缓冲区bufsize:缓冲区大小返回值:成功返回实际写入缓冲区的字节数,失败返回0附加:文件权限修饰位11:setuid,设置用户id10:setgid,设置组id9:sticky,粘附位文件权限修饰位——setuid位setuid位能让普通用户以root用户的角色运行只有root帐号才能运行的程序或命令。例如普通用户运行/usr/bin/passwd命令来更改自己的口令,实际上最终更改的是/etc/passwd文件。但是,/etc/passwd文件是用户信息的配置文件,只有root权限的用户才能更改内容。文件权限修饰位——setuid位对某文件设置setuid位chmodu+s文件名如果文件的拥有者权限原本有x则显示s,否则显示S。文件权限修饰位——setgid位setgid对目录设置后,任何用户在该目录下创建文件的属组都是该目录的属组。chmodg+s目录名文件权限修饰位——setgid位举例:#groupaddtest创建组test#mkdir/home/dir创建目录#chmodo+w/home/dir使其他用户可创建#chgrptest/home/dir修改目录属组为test#chmodg+s/home/dir修改目录setgid位#ls–ld/home/dir查看目录权限以后在/home/dir下新建文件和目录的属组都是/home/dir的属组。文件权限修饰位——sticky位sticky位可以理解为防删除位一个文件是否可以被某用户删除,主要取决于该用户是否对文件所在目录具有写权限。如果没有写权限,则这个目录下的所有文件都不能被删除,同时也不能添加新的文件。如果希望用户能够在某目录添加文件但同时不能删除其他用户文件,则可以对该目录使用sticky位。文件权限修饰位——sticky位chmodo+t目录名举例#useraddu1创建u1用户#touch/home/dir/aa当前用户创建aa#touch/home/dir/bb当前用户创建bb#su-u1后rm/home/dir/aau1删除aaexit退出u1#chmodo+t/home/dir设置sticky位#su-u1后rm/home/dir/bbu1无法删bbexit退出u11415.4dup/dup2重定向将一个文件描述符(新)复制到另一个现有的文件描述符(旧)上,即指向现有的文件表项两个函数dup新描述符是默认当前最小可用的文件描述符dup2新描述符可以通过参数任意指定,如果指定的已经被占用,则自动将其关闭并重新使用1425.4dup/dup2dup #include<unistd.h>
intdup(intfd);参数:现有文件描述符返回值:成功返回新文件描述符(最小可用的文件描述符)错误返回-1(置errno)说明:将最小可用文件描述符指向fd对应的打开文件描述如dup(3)1435.4dup/dup2dup51445.4dup/dup2dup2 #include<unistd.h>
intdup2(intfd,intfd2);参数:fd:旧文件描述符fd2:新文件描述符返回值:成功返回新文件描述符,错误返回-1(置errno)说明:dup2(3,5)与上图示例同理。若fd2已经被使用,则自动关闭fd2用于重定向如dup2(3,1)则关闭1标准输出,并将1复制到3上1455.5文件属性的修改修改文件权限操作
#include<sys/types.h>#include<unistd.h>intchmod(constchar*pathname,mode_tmode);intfchmod(intfd,mode_tmode);两个函数的区别类似stat系列函数说明:除非设置整个权限,否则需要首先调用stat获得mode,然后设置mode,再利用chmod进行修改。1465.5文件属性的修改修改系统umask值文件权限相关概念文件对三组用户有功九种存取权限umask屏蔽字:影响新建文件/目录的权限新建文件或目录权限使用命令方式
文件权限=666&屏蔽字反码
目录权限=777&屏蔽字反码使用系统调用方式文件或目录权限=系统调用中权限&屏蔽字反码命令umask和系统调用umask可以查看或设置屏蔽字1475.5文件属性的修改修改文件的拥有者及组超级用户能修改用户/组,文件拥有者能修改组,其他用户不能修改。#include<sys/types.h>#include<unistd.h>intchown(constchar*pathname,uid_towner,gid_tgroup);intfchown(intfd,uid_towner,gid_tgroup);intlchown(constchar*path,uid_tuid,gid_tgid);三个函数区别类似stat系列函数1485.6案例5:显示文件长格式信息Linux中最常用的一个命令就是ls命令。ls命令用于查看目录信息。ls命令有很多参数选项,其中ls–l可以以长格式显示文件的属性信息。显示的信息包括文件类型、访问权限、文件主人、组、长度、访问日期时间等等。1495.6案例5:显示文件长格式信息见教材。谢谢!Linux程序设计教程第6章目录文件管理152第6章文件目录管理6.1目录基本操作6.2目录其他操作6.3案例6:显示指定目录下文件1536.1目录基本操作打开目录#include<dirent.h>#include<sys/types.h>DIR*opendir(constchar*path);参数:path-目录名返回值:成功返回DIR指针,否则返回NULL(置errno)举例
DIR*d1;d1=opendir(“/home”);if(d1==NULL) perror(“opendir”);1546.1目录基本操作读目录structdirent*readdir(DIR*dirp);参数:dirp-opendir返回的DIR指针返回值:成功回dirent结构体指针,返回NULL表明目录结尾或错误(错误则置errno)说明:每次readdir读出一行记录,即一组文件名字及i节点号。如果要读出目录文件中所有文件的名字,则要使用循环方式调用readdir,直到目录文件结尾。structdirent{ino_td_ino; //i节点号
chard_name[]; //目录下文件/子目录名};1556.1目录基本操作关闭目录intclosedir(DIR*dirp);参数 dirp:opendir返回的DIR指针返回值:
成功返回0,否则返回-1(置errno)举例
DIR*d1;d1=opendir(“/home”);if(d1==NULL) perror(“opendir”);closedir(d1);1566.2目录其他操作改变当前目录 #include<unistd.h>intchdir(constchar*path);参数:path:目录名返回值:
成功返回0,否则返回-1(置errno)注意: chdir切换的是本进程的当前目录,不是shell的当前目录,进程切换对shell的当前目录没影响。1576.2目录其他操作创建目录#include<sys/stat.h>#include<sys/types.h>intmkdir(constchar*pathname,mode_tmode);参数:pathname:要创建的新目录的路径名。 mode:新建目录的权限。返回值:
执行成功时返回0,失败返回-1。1586.2目录其他操作删除目录#include<unistd.h>intrmdir(constchar*pathname);参数pathname:要删除的目录的路径名返回值:成功时返回0,失败返回-11596.3案例6:显示指定目录下文件完成ls显示指定目录下文件列表的功能,如“ls目录”、“ls–l目录”、“ls-l”。1606.3案例6:显示指定目录下文件见教材。谢谢!Linux程序设计教程第7章进程控制163第7章进程控制7.1进程基本概念7.2进程控制7.3什么是Shell1647.1进程基本概念进程进程实体在数据集合上的一次运行过程,是拥有资源和分派资源的基本单位。Linux系统中,要运行一个程序,必须由Linux为此程序创建进程。对多任务系统,内存中会同时驻留多个进程,多进程“并发”执行。只有当某个进程获得其运行所需要的所有资源(包括CPU),它才能够执行;当进程终止后,Linux还要做一些资源收集和清理工作。PCB:structtask_struct,其中记录的信息包括:进程标识符,相关的文件描述符,进程状态,接收的信号等。1657.1进程基本概念进程标识PID每个进程对应一个非负整数,pid_t(有符号整型)最大的PID为32767,每次分配进程id从小开始分配,依次递增,直到最大值后开始使用空闲的最小pid。三个特殊的进程:0,1,2系统第一个进程为init进程,pid为1,以后所有的进程都是通过fork产生的子/孙进程。pstree命令父进程标识PPID除init进程外,每个进程都有由另一个进程创建出来的,该进程称为被创建进程的父进程,而且每个进程都有唯一的父进程。1667.1进程基本概念获取进程标识 #include<sys/types.h>#include<unistd.h>pid_tgetpid(void);获取父进程标识pid_tgetppid(void);1677.1进程基本概念用户标识通常,每个用户有一个唯一的用户ID,创建用户时由系统确定,0为root用户的ID。/etc/passwd帐号:密码:UID:GID:真实姓名:家目录:shellroot:x:0:0:root:/root:/bin/bash每个用户还属于用户组,一个用户可以属于多个用户组,一个用户组中可以有多个用户。/etc/group组名:密码:GID:用户列表bin:x:1:root,bin,daemon进程是通过UID和GID来控制用户对对文件等资源的访问权限的。进程具有的ID(不只这几个)含义实际用户ID创建进程的用户ID有效用户ID进程访问系统资源时的用户ID实际组ID创建进程的用户主组ID有效组ID进程访问系统资源时所属的组
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电离辐射计量员岗位时间管理考核试卷含答案
- 两栖类养殖工技能理论知识考核试卷含答案
- 浆纱浆染工岗位复试考核试卷含答案
- 色彩搭配师安全技能测试评优考核试卷含答案
- 2026年秋季小学班主任分层育人精准施策课件
- 2025年鄄城县数学四年级下学期期中学业质量监测试题含答案解析
- 2026事业单位笔试-重庆-重庆皮肤病与性病学(医疗招聘)历年参考题库含答案详解
- 2026事业单位工勤技能-江西-江西房管员五级(初级工)历年参考题库含答案详解
- 2025年遂溪县数学三年级第二学期期中达标检测模拟试题(含答案解析)
- 大学热学课后试题及完整答案解析
- 2026秋小学科学教科版六年级上册(新教材)教学计划附进度表
- 2026版保密教育线上培训考试题库参考答案
- 招标代理业务内控管理手册
- 2026年秋季统计学专业开学第一课 专业素养与核心竞争力教学设计
- 民族复兴梦(课件)-2026-2027学年统编版道德与法治九年级上册
- 高中数学必修一三角函数单元整体教学设计
- 中国钛合金废料行业市场发展趋势与前景展望战略研究报告
- 可燃液体蒸气爆炸事故应急处置方案
- 第2课时配方法(课件)2026-2027学年人教版数学九年级上册
- 地坪裂缝修补方案设计
- (2025年)“工人阶级重要论述”及“工会十八大精神”知识竞赛试题附答案
评论
0/150
提交评论