unix环境高级编程答案.docx
- 文档编号:16830700
- 上传时间:2023-07-17
- 格式:DOCX
- 页数:19
- 大小:25.74KB
unix环境高级编程答案.docx
《unix环境高级编程答案.docx》由会员分享,可在线阅读,更多相关《unix环境高级编程答案.docx(19页珍藏版)》请在冰点文库上搜索。
unix环境高级编程答案
unix环境高级编程答案
【篇一:
unix环境高级编程--第7章unix进程的环境】
security
标题:
unix环境高级编程--第7章unix进程的环境
发信站:
bbs水木清华站(monmar2715:
53:
352000)
第七章〓unix进程的环境?
7?
1〓引言?
下一章将介绍进程控制原语,在此之前需先了解进程的环境。
在本章中我们将说明:
当执行
一通程序时,其main函数是如何被调用的,命令行参数是如何传送给执行程序的;典型的存
储器布局是什么样式;如何分配另外的存储空间;进程如何使用环境变量;进程终止的不同
方式等。
另外,我们也将说明longjmp和setjmp函数以及它们与栈的交互作用。
在本章结束
之前,我们将查看进程的资源限制。
?
7?
2〓main函数?
一道c程序总是从main函数开始执行。
main函数的原型是:
?
intmain(intargc,char*argv[]);?
其中,argc是命令行参数数,argv是指向参数的各个指针所构成的数组。
在7?
4节中我们将
对命令行参数进行说明。
?
在系统核起动一道c程序时(用一个exec函数,我们将在8?
9节中说明exec函数),在调用mai
n前先调用一个特殊的起动例程。
可执行程序文件将此起动例程指定为程序的起始地址〖cd2
〗这是由连接编辑程序设置的,而连接编辑程序则由c编译程序(通常是cc)调用。
起动例程
从系统核取得命令行参数和环境变量值,然后为调用main函数作好安排。
?
7?
3〓进程终止?
有五种方式使进程终止:
?
1?
正常终止?
(a)从main返回?
(b)调用exit?
(c)调用迹茫模*常病絜xit?
2?
异常终止?
(a)调用abort(第十章)?
(b)由一个信号终止(第十章)?
上节提及的起动例程是这样编写的,使得从main返回后即调用exit函数。
如果将起动例程以
c代码工表示(实际上该例程常常用汇编语言编写),则它调用main函数的形式可能是:
?
exit(main(argc,argv));?
exit和迹茫模*常病絜xit函数?
exit和迹茫模*常病絜xit函数正常终止一个程序:
迹茫模*常病絜xit立即进入
系统核,
exit则先执行一些清除处理(包括的用执行各终止处p2程序,关闭所有标准i/O流等)?
#includestdlib?
h?
voidexit(int?
status);?
?
#includeunistd?
h?
void迹茫模*常病絜xit(int?
status);?
?
我们将在8?
5节讨论这两个函数对其它进程,例如终止进程的父、子进程的影响。
?
使用不同头文件的原因是:
exit是由ansic说明的,而迹茫模*常病絜xit则是由posix?
1
说明的。
?
由于历史原因,exit函数总是执行一个标准i/o库的清除关闭操作:
对于所有打开流调用fcl
ose函数。
回忆5?
5节,这造成所有在缓存中的数据都被刷新(写到文件上)。
?
exit和迹茫模*常病絜xit都带一个整型参数,我们称此为终止状态。
大多数unixshell都
提供检查一个
进程终止状态的方法。
如果(a)若调用这些函数时不带终止状态,或(b)main执行了一个无返
回值的return语句,或(c)main执行隐式返回,则该进程的终止状态是末定义的。
这就意味
着,下列经典性的c语言程序?
#indudestdio?
h?
main()?
{?
〓〓printf(hello,world\n);?
}?
是不完整的,因为main函数没有使用return语句返回(隐式返回),它在返回到c的起动例程
时并没有返回一个值(终止状态)。
另外,若使用?
return(0);?
或者?
exit(0);?
则向启动执行此程序的进程(常常是一个shell进程)返回终止状态0。
另外,main函数的说明
实际上应当是:
?
intmain(void)?
在下一章,我们针会了解到一个进程如何一道程序执行,如何等待执行该程序的进程完成,
然后取得其终止状态。
?
将main说明为返回一个整型以及用exit代替return,对某些c编译程序和unixlint
(1)程序
而言会产生不必要的警告信息。
问题是这些编译程序并不了解在main中的exit与r
eturn语句
的作用相同。
警告信息可能是controlreachesendofnonvoidfunction。
(控
制到达
非void函数的结束处),避开这种警告信息的一种方法是:
在main中使用return语句而不是e
xit。
但是这样做的结果是使我们不能用unix。
?
grep公用程序来找出一道程序中的所有exit调用。
另外一个解决方法是将main说明为返回vo
id而不是int,然后的旧调用exit。
这也避开了编译程序的警告,但从程序设计角度看却并
不正确。
在本章中,我们将main表示为返回一个整型,因为这是ansic和posix?
1所定义的
。
我们将不理会编译程序不必要的警告。
?
atexit函数?
按照ansic的规定,一个进程可以登记多至32个函数,这些函数将由exit自动调用。
我们称
这些函数为终止处理程序,并用atexit函数来登记这些函数。
?
#includestdlib?
h?
intatexit(void(?
?
func)?
(void));?
returns:
0ifok,nonzeroonerror返回:
若成功为0,出错为非0?
其中,参数(*func)(void)是一个函数地址,当调用此函数时无需向它传送任何参数,也不
期望它返回一个值。
exit以登记这些函数的相反顺序调用它们。
同一函数如若登记多次,则
也被调用多次。
?
终止处理程序这一机制是由ansic新引进的。
svr4和4?
3+bsd都提供这种机制。
系统v的早期
版本和4?
3bsd则都不提供此机制。
?
按照ansic和posix?
1,exit首先调用各终止处理程序,然后按需多次调用fclose,关闭所
有打开流。
图7?
1摘要显示了一个c程序是如何起动的,以及它终止的各种方式。
?
p164?
?
图7?
1〓一个c程序是如何起动和终止的?
注意,系统核使一道程序执行的唯一方法是调用一种exec函数。
一个进程自愿终止的唯一方
法是显示或隐式地(调用exit)调用迹茫模*常病絜xit。
一个进程也可非自愿地由一个信号
使其终止(在图7?
1中没有显示)。
?
实例?
程序7?
1说明了如何使用atexit函数。
执行程序7?
1产生:
?
$a?
out?
mainisdone?
firstexithandler?
firstexithandler?
secondexithandler?
注意,在main中我们没有调用exit,而是用了return语句。
?
p165?
?
程序7?
1〓终止处理程序的实例?
7?
4〓命令行参数?
当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序。
这是unixshell的一
部分常规操作。
在前几章的很多实例中,我们已经看到了这一点。
?
实例?
程序7?
2将其所有命令行参数都回送到标准输出上(unixecho
(1)程序不回送第0个参数。
)
编译此程序,并将其可执行代码文件定名为echoarg,则?
$?
/echoargarg1testfoo?
argv[0]:
?
/echoarg?
argv[1]:
arg1?
argv[2]:
test?
argv[3]:
foo?
?
p166?
程序7?
2〓将所有命令行参数回送到标准输出?
ansic和poix?
1都要求argv[argc]是一个空指针。
这就使我们可以将参数处理循环改写为
:
?
for(i=0;arg[i]!
=null;i++)?
7?
5〓环境表?
每个程序都接收到一张环境表。
与参数表一样,环境表也是一个字符指针数组,其中每个指
针包含一个以null符结束的字符串的地址。
全局变量environ则包含了该指针数组的地址。
?
externchar**environ;?
例如:
如果该环境包含了五个字符串,那么它看起来可能如图7?
2中所示。
?
p166?
?
图7?
2〓由五个字符串组成的环境?
其中,在每个字符串的结束处都有一个null字符。
我们称environ为环境指针,指针数组为
环境表,其中各指针指向的字符串为环境字符串。
?
按照惯例,环境由?
name=value?
这样的字符串组成,这与图7?
2中所示相同。
大多数予定义名是完全由大写字母组成的,但
这只是一个惯例。
?
在历史上,大多数unix系统对main函数提供了第三个参数,它就是环境表地址:
?
intmain(intargc,char*argv[],char*envp[]);?
因为ansic规定main函数只有两个参数,而且第三个参数与全局变量environ相比也没有带来
更多益处,所以posix?
1也规定应使用environ而不使用第三个参数。
通常用getenv和puten
v函数(在7?
9节中说明)来存取特定的环境变量,而不是用environ变量。
但是,如果要查看
整个环境,则必须使用environ指针。
?
7?
6〓c程序的存储空间季知?
nbsp;
由于历史原因,c程序一直由下列几部分组成:
?
行的程序(文本编辑程序、编译程序、shell等)在存储器中也只需有一个副本。
另外,正文
段常常是只读的,以防止一道程序由于忌外子故而修改其自身的指令。
?
序中在任何函数之外的说明:
?
intmaxcount=99;?
使此变量以初值存放在初始化数据段中。
?
符,意思是blockstartedbysymbol(由符号开始的块),在程序开始执行之前,系统
核将此段初始化为0。
在函数外的说明?
longsum[1000];?
使此变量存放在非初始化数据段中。
?
返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。
然后,新被调用的
函数在栈上为其自动和临时变量分配存储空间。
以这种方式使用栈,c函数可以递归调用。
?
底之间。
?
图7?
3显示了这些段的一种典型安排方式。
这是一个程序的逻辑布局一虽然并不要求一个具
体实现一定以这种方式安排其存储空间。
尽管如此,这给出了一个我们便于作有关说明的一
种典型安排。
?
?
?
p168?
图7?
3〓典型的存储器安排?
【篇二:
unix环境高级编程中文件操作】
前我们都学过如何用c标准i/o库读写文件,这些i/o操作是如何实现的?
其实所有的i/o操作最终都要在内核中执行。
只不过我们用的c标准i/o库函数先通过系统调用把i/o操作从用户空间传给内核,然后再让内核去做i/o操作而已。
?
现在看看c标准i/o库函数是如何用系统函数实现的。
一、fopen
调用open打开指定的文件,返回一个文件描述符(也就是一个int型的编号),分配一个file结构体,这个file结构体中包含该文件的文件描述符、i/o缓冲区和当前读写位置等信息,最后返回这个file结构体的地址。
二、fgetc
通过传入的file*参数找到该文件的描述符、i/o缓冲区和当前读写位置,判断能否从i/o缓冲区读到下一个字符,如果能读到就直接返回给字符,因为fgetc一次就是只读一个字符,如果读不到就再次调用read函数,read函数将文件描述符传进内核,让内核读取该文件的内容到缓冲区中
需要注意的是:
对于c标准i/o库函数来说,打开的文件用file*指针标识,而对于内核来说,打开的文件由文件描述符标识,文件描述符从open系统调用获得,在使用read,write,close系统调用时都需要传文件描述符
三、fputc
判断该文件的i/o缓冲区是否有空间再存放一个字符,如果有空间则直接保存在i/o
缓
冲区中并返回,如果i/o缓冲区已满就调用write,让内核把i/o缓冲区的内容写到文件。
四、fclose
如果i/o缓冲区中还有数据没有写回文件,就调用write写回文件,然后调用close关闭文件,释放file结构体和i/o缓冲区。
?
open、read、write、close等系统函数称为无缓冲i/o函数,因为它们位于c标准库的i/o
缓冲区的底层,用户程序在读写文件时即可以去调用c标准i/o库函数,也可以直接调用底层的系统函数,标准i/o库函数是有缓冲区的,系统函数是无缓冲区的,究竟用哪一组函数更好一些呢?
?
1、对于普通文件的读和写,我们最好用c标准库函数,因为c标准i/o库函数已经为我
们开辟好了缓冲区,省去了我们自己开辟,自己管理缓冲区的麻烦。
对于网络编程,我们只能够用系统函数。
2、在读写网络设备时通常是不希望有缓冲的,比如qq聊天,你不可能非得说完很多的话,并且还要将缓冲区填满之后再发送给对方吧!
如果真那样的话,那就不叫聊天了,叫写信,并且也失去了你问我答的效果。
所以网络编程就需要使用无缓冲区的系统函数,网络编程在unix系统编程中占据了极为重要的位置
pcb与文件描述符的关系
?
linux是多用户、多任务的操作系统,每个进程在内核中都有一个task_struct结构体来维护本进程有关的信息,即进程控制块(pcb),pcb中包含该进程打开的所有文件的信息,其中有一个成员是文件描述符表(见下面的结构体,可以看出是一个数组),每个表项都是一个指针,指向一个已打开文件,表项的下标就是文件描述符。
?
1、structtast_struct
?
?
?
?
?
?
?
?
?
2、
?
?
?
?
?
?
?
?
?
?
?
?
3、
?
?
?
?
?
?
?
?
?
?
?
?
?
?
{structfile_struct*fds[1024];:
:
:
n个成员;}从这个结构体中我们可以看出一个进程最多可以打开1024个文件structfile_struct{chark_buf[4096];intrw_pos;into_flags;:
:
:
总共100多项}k_buf是内核缓冲区,用于预读入和缓输出,一次读入或者输出4kb的数据。
rw_pos是当前文件的读写位置,o_flags保存打开文件的标志,是读啊还是写。
file*my_fopen(char*file_name,char*mode){file*fp=null;intfd,flags;fp=(file*)malloc(sizeof(file));if(*mode==?
r?
)flags=o_rdonly;elseflags=o_wronly;fd=open(file_name,flags);fp-_fileno=fd;returnfp;}
?
4、
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
file*my_fopen(char*file_name,char*mode){file*fp=null;intfd,flags;fp=(file*)malloc(sizeof(file));if(*mode==?
r?
)flags=o_rdonly;elseflags=o_wronly;fd=open(file_name,flags);fp-_fileno=fd;returnfp;}
?
read函数
?
在用户程序中文件描述符指的是文件描述符表的索引,执行程序时系统会自动打开三个
?
#definestdin_fileno0
?
#definestdout_fileno1
?
#definestderr_fileno2
?
一、open函数
?
open函数可以打开或者创建一个文件,所需要的头文件为:
?
#includesys/types.h
?
#includesys/stat.h
?
#includefcntl.h
?
?
函数原型为:
?
intopen(constchar*pathname,intflags);
?
intopen(constchar*pathname,intflags,mode_tmode);
?
我们看到open函数有两种形式,一个带两个参数,一个带三个参数,其实open函数是
这样声明的:
?
intopen(constchar*pathname,intflags,…);
?
最后的可变参数可以是0个或1个,由flags参数中的标志决定。
?
?
pathname参数是要打开或创建的文件名,和fopen一样,pathname既可以是相对路径
也可以使绝对路径,如果只有文件名就表示相对于当前目录。
flags参数有一系列常数值可供选择,可以同时选择多个常数用按位或运算符连接起来,所有这些常数的宏定义都以o_开头,表示or。
open函数的flags参数分为必选项和可选项。
?
必选项:
以下三个常数中必须指定一个,且仅允许指定一个。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
o_rdonly只读打开o_wronly只写打开o_rdwr可写可读打开可选项有很多,这里只列出常用的几个。
o_append追加o_creat若此文件不存在则创建它o_trunc将文件截断为0.注意:
open函数和c标准库函数fopen有些细微的区别:
1、以写的方式fopen一个文件时,如果文件不存在会自动创建,以写的方式open一个文件时,只有明确指定o_creat选项时才会创建文件,否则文件不存在就出错返回。
2、以w或w+方式fopen一个文件时,如果文件已经存在就截断,以写方式open一个文件时,必须明确指定trunc才会截断文件,否则直接在原来的数据上改写。
3、只有当第二个参数中指定了o_creat选项时,才需要第三个参数,它用来指定要创建文件的权限,一般为0644。
举例:
在程序xue.c中打开一个文件,代码就是open(“somefile”,o_wronly|o_creat,0644);
?
open函数的返回值:
?
成功的话返回值为文件描述符,失败返回-1,同时设置errno为相应的值,由open返
回的文件描述符一定是该进程未使用的最小描述符,一个程序开始执行时自动占用文件描述符0,1,2,因此第一次调用open就会返回描述符3,在调用open一次就返回4。
?
举例
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
#includestdio.h#includestdlib.h#includeunistd.h#includefcntl.hintmain(intargc,char*argv[]){intfd=0;intn=0;charbuf[1024]={0};fd=open(temp.txt,o_rdonly)if(-1==fd){perror(openfile.txt:
);exit
(1);}while((n=read(fd,buf,1024))0)
【篇三:
linux编程大作业题目】
>要求:
这部分题目必做,要详细回答,最好用自己理解的语言回答,有些题目可用图形和举例等阐述问题。
1、makefile文件的作用是什么,makefile文件中有一种变量,其值是根据具体的规则来确定的,称为自动变量,其中代表所有依赖文件列表的是哪个;举例说明make命令的工作流程。
2、什么是进程,什么是线程,它们之间有何差别,请编程说明。
3、简述linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程。
解释i节点在文件系统中的作用。
4、文件指针file*与文件描述符是一个什么样的关系,请画图说明。
5、简述与windows的文件系统相比,linux文件系统有什么特点,并用图详细描述。
6、linux创始人是谁,linux操作系统的诞生、发展和成长过程始终依赖着的重要支柱有哪些,并描述linux的特点。
7、为什么要学习linux开源技术。
8、linux的主要组成包括什么。
9、什么是linux内核,它的作用是什么。
什么是linux的内核版本和发行版本?
10、什么是符号链接,什么是硬链接?
符号链接与硬链接的区别是什么?
第二程序设计题目
要求:
?
shell程序设计部分、文件和目录部分、进程和信号部分、网络编程部分则必做(其中前3部分选作5道题目,网络编程为自学部分,选作2道题目)。
?
若做综合设计题目或自拟综合设计题目,则shell程序设计部分、文件和目录部分、进程和信号部分、网络编程部分可不做。
shell程序设计部分
1、设计shell脚本程序,运行结果如下:
----------------
linux13/06/11
----------------
a:
查看进程信息
b:
查看用户信息
c:
显示当前目录信息
d:
退出
---------------
当用户输入相应的数字执行相应的功能。
2、设计shell脚本程序,在屏幕上输出操作系统的信息,包括
计算机名、linux分发版本名称、linux内核版本和当前的ip地址。
3、设计shell脚本程序,要求用户对/home目录下的文件进行备份,压缩为linux系统中常用的tar.gz格式。
4、设计shell脚本程序,假设用户建立了目录a和目录b,目录中不包含子目录,要求用户编写一个脚本程序,比较两个目录内文件的差异。
5、设计一个shell程序,添加一个新组为class1,然后添加属于这个组的30个用户,用户名的形式为stdxx,其中xx从01到30。
6、设计一个shell程序计算n的阶乘。
要求:
(1)从命令行接收参数n;
(2)在程序开始后立即判断n的合法性,即是否有参数,若有是否为正整数,若非法请给错误提示;
(3)最后输出计算的结果。
7、设计一个shell程序,在每月第一天备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式yymmdd_etc,yy为年,mm为月,dd为日。
8、判断当前工
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- unix 环境 高级 编程 答案