• 28.25 KB
  • 2022-04-22 11:34:00 发布

北京化工大学《Linux和Unix编程基础》课程期末复习题参考答案.docx

  • 18页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'北京化工大学《Linux和Unix编程基础》课程期末复习题参考答案注意事项:1、如下题目为易老师在2016-2017学年秋季学期该门课留下的期末复习题,不确保每年留的期末复习题完全一致。2、如果是易老师上这门课,平时上课、上机缺勤对期末考试成绩的确基本没影响。期末成绩基本就靠期末考试的发挥。期末考题跟复习题不会一模一样,期末考题要么会加多一两问,要么某些限制条件会变。注意期末考试时间只有90分钟,3道简答题(各15分),3道编程题(头一题15分,后两题各20分),作答时间会非常紧,4.33并不好拿。期末考后3天就会出成绩。老师说如果整体成绩极为不理想时期末给分会比卷面原始分高一点点。3、之所以复习题范围画得如此之小就是因为在网上基本搜索不出答案,如下答案也仅仅是学霸们凭自己习得的知识给出的参考答案,跟标准答案可能有所出入。给出这份参考答案的同学在这门课取得了94分。4、2016-2017学年期末考题基本源自该复习题简答题第2、4、5题及编程题第1、3、6题。简答题:1.Linux文件系统怎样通过i-node号存储文件?I-node用于储存文件的属性,比如文件的所有者、文件的创建日期、修改日期、文件的大小等等,中文译名为"索引节点"。每当要存储一个新文件时,内核先找到一个空的i-node,将上文提到的文件属性记入i-node中。内核在数据区寻找足够的自由块存放文件内容,并将数据块序列存入i-node的磁盘分布区。最后内核将i-node号和文件名一起作为入口 记入当前目录中。目录是一种包含了i-node号和文件名的表的文件。每个i-node都有唯一的一个号码,Unix/Linux操作系统用i-node号码来唯一标识不同的文件。因此一个文件可以有多个文件名,但他们都共同拥有一个i-node号,即指向同一个文件。Unix/Linux系统内部不使用文件名,而使用i-node号码来识别文件。对于系统来说,文件名只是i-node号码便于识别的别称或者绰号。1.以lseek和write函数为例说明竞争与原子操作?计算机操作最重要的构成单位是原子操作。原子操作是一种不可再细分的操作,或者在系统中其他处理器看来是不可再分了。在用如下的代码将登录和退出记录添加到wtmp日志文件时:lseek(fd,0,SEEK_END);write(fd,&rec,len);Unix是一个分时系统,这个过程需要两个独立的步骤lseek和write时间1:B的登录进程定位文件的末尾时间2:B的时间片用完,A的登录进程定位文件的末尾时间3:A的时间片用完,B的登录进程写入记录时间4:B的时间片用完,A的登录进程写入记录这种情况叫做竞争。由于这两个进程产生竞争,A的记录覆盖了B的记录,B的登录记录丢失。对lseek和write调用是独立的系统调用,内核可随时打断进程,从而使其被中断如果将O_APPEND标志位置位,启动自动添加模式,则内核将lseek和write组 合成原子操作,被组合为不可分割的单元,则可以解决问题。具体来说,每个对write的调用自动调用lseek将内容添加到文件的末尾。启动自动添加模式的代码:#includeints;s=fcntl(fd,F_GETFL);s|=O_APPEND;result=fcntl(fd,F_SETFL,s);if(result==-1)perror(“settingAPPEND”);elsewrite(fd,&rec,1);3.设备文件和磁盘文件的相同和不同处?相同处:磁盘文件与设备文件都有文件的属性、文件的修改时间、文件的节点、文件名等等之类的,都可用系统的库函数与C语言的库函数来进行open、read、write、close来进行操作。文件权限位以同样的方式应用于控制设备文件和磁盘文件的访问。不同处:/*1、磁盘文件的字节数就是磁盘文件的大小,而设备文件显示文件大小的地方显示的是设备的主设备号和从设备号。主设备号确定处理该设备实际的子程序,而从设备号被作为参数传输到该子程序。*/ 2、i-节点的类型会记录在结构stat的成员变量st_mode中的类型区域中。磁盘文件的i-节点包含指向数据块的指针,而设备文件的i-节点包含指向内核子程序表的指针。3、当内核要准备为文件读数据时,首先会看文件的文件节点属性,如果文件节点对应的是磁盘文件的话,则直接根据文件系统的块分配表读取数据,如果是设备文件的话,则会调用设备文件的驱动程序的read方法进行读取。其他文件操作例如open,write,lseek,close都类似。/*4、磁盘文件在进行读写的时候是有缓冲区的,而设备文件是没有缓冲区的。*/5、系统到磁盘文件的连接在处理和传输数据方面不同于到设备文件的连接,与磁盘文件的连接通常包含内核缓冲区,从进程到磁盘的字节先被缓冲,然后才从内核的缓冲区被发送出去。到终端的连接则通常没有,进程需要尽快把到终端的数据传送出去。4.符号链接与硬链接的概念与不同处?概念:硬链接:硬链接是将目录链接到树的指针,同时也是将文件名和文件本身链接起来的指针。硬链接不能指向其它(文件)系统中的i-节点。即使根也不能生成到目录的链接。 符号链接:符号链接通过名字引用文件,而不是i-节点。可以将符号链接理解为Windows下的快捷方式。不同处:1、硬链接不能跨越文件系统,而符号链接可以。2、硬链接不能生成到目录的链接,而符号链接可以指向目录。3、硬链接原文件&链接文件公用一个i-node号(i-node号不唯一),说明他们是同一个文件,而符号链接原文件&链接文件拥有不同的i-node号,它们i-节点号唯一,表明他们是两个不同的文件。4、在文件属性上符号链接会在文件类型点标记l,明确标明是链接文件,而硬链接没有明确标记,因为在本质上硬链接文件和原文件是完全平等关系。/*5、链接数目是不一样的,软链接的链接数目不会增加,文件大小是不一样的,硬链接文件显示的大小是跟原文件是一样的,而这里软链接显示的大小与原文件就不同了。*/5.编写脚本文件,从终端读入两个数,比较大小并输出比较结果。#!/bin/bashread-p"请输入第一个数:"aread-p"请输入第二个数:"bif[$a-gt$b]thenecho"$a>$b"elif[$a-eq$b]then echo"$a=$b"elseecho"$a<$b"fi6.简述终端的规范模式和非规范模式。规范模式:驱动程序输入的字符保存在缓冲区,并且仅在接收到回车键或者EOF键时才将这些缓冲的字符发送到程序。缓冲数据使驱动程序可以实现最基本的编辑功能,如删除字符、单词直至整行。当用户按下删除键、单词删除键或是终止键时,这些功能就会被调用。被指派到这些功能的特定键在驱动程序里设置,可通过命令stty或系统调用tcsetattr来修改。非规范模式:当缓冲和编辑功能被关闭时,处于非规范模式。终端处理器仍旧可以进行特定的字符处理,例如,处理Ctrl-C及换行符和回车符的转换,但用于删除、单词删除和终止的编辑键没有特殊意义,因此相应的输入会被视作常规的输入。命令stty-icanon可以关闭规范模式,关闭termios结构中的c_flag字段的ICANNON标志就能使终端处于非规范模式。编程题:1.实现whoami命令。#include#include #include#includeintmain(intac,char*av[]){uid_tid;structpasswd*p;id=geteuid();p=getpwuid(id);if(p==NULL){perror(*av);return-1;}elseprintf("%sn",p->pw_name);return0;}1.实现writeuser命令。#include#include#include#include /**purpose:sendmessagestoanotherterminal*method:opentheotherterminalforoutputthen*copyfromstdintothatterminal*usage:write1username*/intmain(intac,char*av[]){intfd;charbuf[BUFSIZ];char*get_tty(),*tty_for_user;if(ac!=2){fprintf(stderr,"usage:writeusernamen");exit(1);}tty_for_user=get_tty(av[1]);if(tty_for_user==NULL)return1;sprintf(buf,"/dev/%s",tty_for_user);fd=open(buf,O_WRONLY);if(fd==-1){perror(buf);exit(1); }while(fgets(buf,BUFSIZ,stdin)!=NULL)if(write(fd,buf,strlen(buf))==-1)break;close(fd);}char*get_tty(char*logname)/**purpose:findthettyatwhich"logname"isloggedin*returns:astringorNULLifnotloggedin*errors:doesnothandlemultiplelogins*/{staticstructutmputrec;intutfd;intnamelen=sizeof(utrec.ut_name);char*retval=NULL;if((utfd=open(UTMP_FILE,O_RDONLY))==-1)/*openutmp*/returnNULL;/*lookforalinewheretheuserisloggedin*/ while(read(utfd,&utrec,sizeof(utrec))==sizeof(utrec))if(strncmp(logname,utrec.ut_name,namelen)==0){retval=utrec.ut_line;break;}close(utfd);/*close&go*/returnretval;}1.创建两个进程,第一个进程设置终端为非规范模式,第二个进程睡眠5秒后设置终端为规范模式。#include#includeintmain(intac,char*av[]){intbefore;before=fork();if(before==-1)perror("fork");elseif(before!=0) {structtermiostt;tcgetattr(0,&tt);tt.c_lflag&=~ICANON;tcsetattr(0,TCSANOW,&tt);}else{sleep(5);structtermiostt;tcgetattr(0,&tt);tt.c_lflag|=ICANON;tcsetattr(0,TCSANOW,&tt);}return0;}1.测试某文件是否为符号链接?#include#include#include#includeintmain(intac,char*av[]){ structstatinfo;if(ac>1){if(stat(av[1],&info)!=-1){if((info.st_mode&S_IFMT)==S_IFLNK)printf("Thisisasymobliclink.n");elseprintf("Thisisnotasymobliclink.n");}}else{perror(av[1]);return-1;}return0;}1.不想被write程序打扰可以使用mesg命令,请编写这样的程序。#include#include#include#include intmain(intac,char*av[]){structstatsettings;intperms;if(fstat(0,&settings)==-1){perror("Cannotstatstdin");exit(0);}perms=(settings.st_mode&07777);/*ALLPERMSinstat.h*//**ifnoargs,reportsetting*/if(ac==1){printf("is%cn",(perms&S_IWGRP)?"y":"n");exit(0);}/**Hasargs-checkthemandupdateifok*/if(ac==2&&av[1][0]=="n")perms&=~S_IWGRP;elseif(ac==2&&av[1][0]=="y")perms|=S_IWGRP; else{fprintf(stderr,"usage:mesg[y|n]n");exit(2);}if(fchmod(0,perms)==-1){perror("Cannotchangemesgstatus");exit(3);}return0;}1.编写cpfile1file2,事项Y/N提示覆盖已有文件功能,同时把file1的权限、最后访问时间和最后修改时间赋予给file2。#include#include#include#include#include#include#include#defineBUFFERSIZE4096voidoops(char*,char*);intmain(intac,char*av[]){ intin_fd,out_fd,n_chars;charbuf[BUFFERSIZE];char*file1=NULL,*file2=NULL;structstatf1;inta=stat(av[1],&f1);inti_option=0;while(--ac)/*checkargs*/{if(strcmp("-i",*++av)==0)i_option=1;elseif(!file1)file1=*av;elseif(!file2)file2=*av;elseusage();}if(!file1||!file2)usage();/*openfiles*/if((in_fd=open(file1,O_RDONLY))==-1)oops("Cannotopen",file1);if(!i_option||!exists(file2)||ok_to_replace(file2)) if((out_fd=creat(file2,f1->st_mode))==-1)oops("Cannotcreate",file2);structutimbufti;ti.actime=f1->st_atime;ti.modtime=f1->st_mtime;if(utime(file2,&ti)==-1)oops("Cannotsendtime.",file2);/*copyfiles*/while((n_chars=read(in_fd,buf,BUFFERSIZE))>0)if(write(out_fd,buf,n_chars)!=n_chars)oops("Writeerrorto",file2);if(n_chars==-1)oops("Readerrorfrom",file1);/*closefiles*/if(close(in_fd)==-1||close(out_fd)==-1)oops("Errorclosingfiles","");return0;}voidoops(char*s1,char*s2){fprintf(stderr,"Error:%s",s1);perror(s2);exit(1); }voidusage(){fprintf(stderr,"usage:cp[-i]file1file2n");exit(1);}/**newfunctionstosupportthe"-i"option**exists(char*filename)-usesopen()toseeiffileisthere*Abetterchoiceisstat()-seeChapter3*ok_to_replace(char*fn)-asktheuser*/intexists(char*filename){intfd;if(fd=open(filename,O_RDONLY))close(fd);return(fd!=-1);}/**ok_to_replace-promptstostderrandreadsfromstdin*/ intok_to_replace(char*filename){charans[10];/*oughttobeenoughfory/n*/charc;intretval=0;fprintf(stderr,"cp:Oktoreplace`%s"?",filename);if(scanf("%9s",ans)==1){if(*ans=="y"||*ans=="Y")retval=1;}while((c=getchar())!=EOF&&c!="n");returnretval;}'