Linux系统程序设计教程(第2版)习题参考答案_第1页
Linux系统程序设计教程(第2版)习题参考答案_第2页
Linux系统程序设计教程(第2版)习题参考答案_第3页
Linux系统程序设计教程(第2版)习题参考答案_第4页
Linux系统程序设计教程(第2版)习题参考答案_第5页
已阅读5页,还剩23页未读, 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章

一、选择题

题号答案题号答案

1B7C

2C8D

3A9D

4B10A

5A11C

6B12B

二、简答题

I.简述Linux系统的各种版本的命名方式。

第一•种方式用于1.0版本之前(包括1.0)。第一个版本是0.01,紧接着是0.02、0.03、

0.10>0.11、0.12、095、0.96、0.97、0.98、0.99和之后的1.0。

第二种方式用于1.0版本之后到2.6版本,数字由3部分“A.B.C”组成,A代表主版本

号,B代表次主版本号,C代表较小的木版本号。

第三种方式从2004年的2.6.0版本开始使用。2.6版本采用“A.B.C.D”形式;C随着新

版本的发布而增加,D代表一些bug修复、安全更新、新特性和驱动的次数。3.0版本之后

采用“A.B.C”格式,B随着新版本的发布而增加,C代表一些bug修复、安全更新、新特

性和驱动的次数。第三种方式中不再使用偶数代表稳定版本、奇数代表开发版本的命名方式。

2.简述Linux系统的特点。

(1)开放性。

(2)多用户。

(3)多任务。

(4)良好的用户界面

(5)设备独立性

(6)丰富的网络功能

(7)可靠的系统安全

(8)良好的可移植性

3.简述系统调用与库函数的区别和联系。

联系:系统调用和库函数都以C函数形式出现,提供给用户一种功能实现的接口,需

要用户输入指定的参数,调用结束得到指定的返回值。

区别:系统调用是程序获得内核服务的接口,库函数是在系统调用上层的函数,有的库

函数是需要调用一个或多个系统调用来实现的。

4.完成如下命令

(1)新建用户tom和用户组student

#useraddtom

#passwdtom

#groupaddstudent

(2)新建文件file

#touchfile

(3)将文件file改名为又st,然后将test拷贝到/home

#mvfiletest

#cptest/home

(4)将/home/test文件的羽有着修改为tom,将文件所属组该为student

#chowntom:studen(/home/test

第2章

一、填空题

1.插入模式、命令模式、末行模式。

2.预处理、编译、汇编、链接。

3.Makefile

4.make

5.静态库,共享库

二、选择题

题号答案题号答案

1B7A

2D8C

3B9A

4D10C

5B11C

6C12B

三、简答题

1.静态库与共享库有什么区别?

(1)静态库文件以.a结尾,共享库文件以.so结尾。

(2)静态库的代码在编译时就已连接到应用程序中,共享库只是在程序开始运行时才

载入,在编译时,只是简单地指定需要使用的库函数。

(3)静态库生成的可执行文件可以直接运行,共享库生成的可执行文件需要提供共享

库才能运行。

(4)静态库生成的可执行文件相对比较大,共享库生成的可执行文件相对比较小。

2.Makefile文件的显式规则是什么?

目标文件:依赖文件列表

vtab>更新目标文件使用的命令

四、编程题

1.编写makefile:当前目录下有文件al.ca2.ca3.c,其中al.c中带有main函数,其他文件

为用户自定义函数供main函数调用,编写完成对这几个文件的编译工作生成可执行文件a

CC=gcc

BIN=a

S(BIN):al.oa2.oa3.o

$(CC)-o$(BIN)$A

al.o:al.c

$(CC)-cal.c

a2.o:a2.c

$(CC)-ca2.c

a3.o:a3.c

$(CC)-ca3.c

clean:

rm-f*.oS(BIN)

2.编写makefile:当前目录下有很多独立的程序文件:aa.cbb.Ccc.c(即每个文件中都有

main函数),分别要生成对应的我可执行文件aabbcc,为了方便用户操作,写一个makefilc

使得调用make命令会重新编译最新修改的程序文件

CC=gcc

ALL:aabbcc

aa:aa.c

$(CC)-oaaaa.c

bb:bb.c

$(CC)-obbbb.c

cc:cc.c

$(CC)-occcc.c

clean:

rm-faabbcc

第3章

一、选择题

题号答案题号答案题号答案题号答案题号答案

1C7B13B19D25C

2A8C14B20D26B

3B9D15C21A

4C10C16B22B

5B11C17C23D

6A12A18D24A

二、填空题

1.main

2.命令行参数个数,指向各命令行参数字符串的指针数组

3.time」类型、structtm类型、字符串形式

4.timet,1970年1月1口零时到当前时间的秒数

5.localtime

6.ctime

7.structtm,time_t

8.t4-r

三、编程题

1.如果一个用户输入一个参数,则打印“noargs",如果输入两个参数并且第二个命令行参

数是-a,则打印u\willdealwith-av,如果是-1则打印"Iwilldealwith-I”

#include<stdio.h>

intmain(intargc,char*argv[])

(

if(argc==l)

printf("noargs\nM);

elseif(argc==2)

|

if(strcmp(argv[I],',-a")==0)

printf("Iwilldealwith-a\nu);

if(strcmp(argv[1],"-l")==0)

printf("Iwilldealwith-l\n");

I

rctuni0;

I

2.获取当前系统的时间,并按命令date的显示方式显示出来。

#includc<stdio.h>

#iDelude<stdlib.h>

#includc<tinic.h>

/*

*调用localtiinc获取Linux系统日期时间

*/

intmain(intargc,char*argv[]){

time_tt;

structtin*p_tm;

time(&t);

p_tm=localtiinc(&t);

printf("%d年%d月%d日%d时%d分%d秒\n",

p_tm->tm_year+1900,

p_tm->tm_mon+1,

p_trn->iin_mday,

p_tm->tm_hour,

p_tm->tm_min,

p_tm->tm_sec);

return0;

3.由用户输入年、月、日、时、分、秒,并将该时间设置为系统时间。

#include<stdio.h>

#includc<stdlib.h>

#include<time.h>

/*

*此例程为调用stime设置Linux系统日期时间

*注意:stime需要root权限

*/

chartip[]="需要输入年月日时分秒6个参数\n";

intmain(inlargc,char*argv[]){

if(argc==7){

t;

structtm*p_tm;

p_tm=localtime(&t);

intyear=strtol(argv[l],NULL,10);

intmon=strtol(argv[2],NULL,10);

intday=strtol(argv[3],NULL,10);

inthour=strtol(argvl4],NULL,10);

intmin=strtol(argv[5],NULL,10);

intsec=strtol(argv[6],NULL,10);

printf("%d%d%d%d%d%d",year,mon,day,hour,min,sec);

p_tm->tm_year=year-1900;

p_tm->tm_mon=mon-1;

p_tm->tm_mday=day-I;

p_tni->tm_hour=hour;

p_tm->tm_min=min;

p_tm->tm_sec=sec;

t=mk(ime(p_tm);

stime(&t);

}else{

printf("%s\n",tip);

I

return0;

第4章

一、选择题

题号答案题号答案题号答案

1B7C13B

2B8C14C

3C9A

4C10B

5A11D

6B12B

二、填空题

1.STDIN_FILENO、STDOUT_FILENO.STDERR_FILENO,0,1,2

2.rw--wxr-x,SJRUSR|S」WUSR|S」WGRP|SJXGRP|S_IROTH|S」XOTH

3.打开或创建文件

4.O_RDONLY、O_WRONLY、O_RDWR。

5.下一次读或写的位置

6.-4,SEEK.CUR

7.O_TRUNC,truncate

8.644,755

9.642,753

10.0724,O_RUSR|O_WUSR|O_XUSR|O_WGRP|O_ROTH

11.r--w--x,()421

三、简答题

1.Linux文件类型主要有哪七类?

常规文件、目录文件、字符设备文件、块设备文件、管道文件、链接文件、套接字文件

2.简述文件、inode、文件名、目录之间的关系。

每个存在磁盘上的文件都由i节点和数据块两部分组成,i节点和文件一一对应,一个

i节点可以对应多个文件名,文件名和i节点的对应关系叫做文件的硬链接,文件名用i节

点的对应关系保存在目录文件中。

3.什么是文件描述符?

(1)一个非负整数,内核以此来标识一个特定进程正在操作的文件。

(2)012代表三个标准的文件描述符,分别为标准输入、标准输出、标准错误输出

4.使用符号方式表示rwxrwxrwx权限

S」RUSR|S」WUSR|S」XUSR|S」RGRP|S」WGRP|S」XGRP|S」ROTH|

S_IWOTH|S_IXOTH

5.写出。pen以下6种打开标志:只读、只写、读写、追加、文件不存在创建、截断为

0

O_RDONLYO_WRONLYO_RDWRO_APPENDO_CREATO_TRUNC

6.读程序,写出执行结果并解释得到该结果的原因

main()

intfdl.fd2;

fd1=open('7etc/passwd”,O_RDONLY);

fd2=open(t7etc/passwd,\O_RDWR);

prinlf(i4fdl=%d,fd2=%d\nM,fdl,fd2);

close(fdl);

close(fd2);

I

结果:fdl=3fd2=4

原因:open返回的文件描述符为最小可用的非负整数,012是三个标准的文件描述符默

认已经被占用,所以第一个叩en的返回值为3,第二个open返回的是4。

四、编程题

1.向文件门中写入“helloworld!”,然后再将fl中的内容读出并显示在屏幕上。(注

意必要的错误判断)

:include<unistd.h>

#includc<sys/stat.h>

#include<sys/tcntl.h>

intmain()

{

intfd;

charbufl[13]={"helloworld!"};

charbuf2f12];

intnum;

fd=open(fl",O_RDWR|O_CREAT|O_TRUNC,0644);

if(fd==-l)

(

peirorC'flnotopen");

exit(l);

I

num=write(fd,buf1,sizeof(buf1)-1);

if(num!=(sizeof(bufl)-1))

printfC'writelessthanwant\n");

lseek(fd,O,SEEK_SETi;

num=read(fd,buf2,12);

if(num!=12)

printf("readlessthan12\n");

write(l,buf2,12);

close(fd);

2.向文件C2中写入“aabbeeddee”,然后将偏移量移到绝对值偏移为4的位置处,读6个

字符,并将结果显示在屏幕上

#inckide<unistd.h>

#include<sys/stat.h>

#include<sys/fcntl.h>

intmain()

{

inifd;

charbuf1[11]={"aabbccddee");

charbuf2llO];

intnum;

fd=open(“f2",0_RDWR|O_CREAT|O.TRUNC,0644);

if(fd==-l)

{

perror("f2notopen");

exit(l);

)

num=write(fd,buf1,sizeof(buf1)-1);

if(num!=(sizcof(buf1)-1))

printf(uwritelessthanwant\n");

lseck(fd,4,SEEK_SET>;

nuin=read(fd,buf2,6);

if(num!=6)

printf(ureadlessthan6\n");

write(l,buf2,6);

closc(fd);

1

3.向文件f3中写入"aabbccddccffgghh",然后将文件截短后的文件内容读出并显示在屏

幕上

#include<unistd.h>

#include<sys/stat.h>

#include<sys/fcntl.h>

intmain()

{

intfd;

charbufI[17]={"aabbccddeeffgghh"};

charbuf2[8];

intnum;

fd=open("f3"Q_RDWR|O.CREAT|O_TRUNC,0644);

if(fd==-1)

{

pcrror("f3notopen");

exit(i);

}

nuin=write(fd,bufl,sizeof(bufl)-l);

if(num!=(sizeof(buf1)-1))

printf("writelessthanwant\n");

lseek(fd.O,SEEK_SETi;

ftruncate(fd,8);

num=read(fd.buf2.8);

if(num!=8)

printf("readlessthan8\n");

write(1,buf2,8);

close(fd);

|

4.在程序中将umask改至044,创建文件f4

#include<unistd.h>

#includc<sys/stat.h>

/include<sys/fcntl.h>

intmain()

(

intfd;

umask(044);

crcat(',f4,,,S_IRUSR|SJWUSR);

1

5.实现“cal文件名”显示文件内容

#inchide<fcntl.h>

main(intargc,char*argv[j)

{

intfd;

intnum;

charbuf[10];

if(argc!=2)

(

printf("missfilename\n");

exit(l);

)

fd=open(argv[1],O_RDONLY);

if(fd==-l)

(

perror("erroropen");

exil(l);

)

while((num=read(fd,buf,10))!=0)

write(1,buf,num);

closc(fd);

6.实现“cp原文件目标文件”

#include<sys/stat.h>

#include<fcntl.h>

main(in(argc,char*argv[])

{

intfrom,to;

ininum;

charbuf[10];

if(argc!=3)

{

printf("argumenlerror\n");

exit(l);

)

from=open(argv[1],O_RDONLY);

to=opcn(argvl2],O_WRONLY|O_CREAT|O_TRUNC,0644);

num=read(from,buf.10);

while(num!=0)

(

write(to,buf,num);

num=rcad(from,buf,10);

}

closc(from);

close(to);

)

第5章

一、选择题

题号答案题号答案

1C7B

2A8A

3B9C

4C10A

5B11D

6C12A

二、填空题

I.umask

2.link,symlink

3.gctcwd

4.stat或fstat或Istat

5.更改文件权限,更改文件所有者和所属组,更改文件访问时间和修改时间

6.dup2(6J)

三、判断并解释原因

1.错2.错3.错4.错5.错

四、简答题

I.回答stat、fstat、latal三个系统调用的区别

scat根据路径获得文件元数据信息

fstat根据文件描述符获得文件元数据信息

前两者如果遇到符号迸接文件则会一直引用至非符号铳接文件

Istat获得符号链接文件本身的文件元数据信息

2.dup和dup2的区别和联系

联系:dup与dup2都用来将新文件描述符指向原来文件描述符指向的打开文件描述。

区别:dup返回的新文件描述符为最小可用的文件描述符,dup2返回的新文件描述符可

以通过第二个参数指定。

3.硬链接和符号链接的区别

(1)命令

In原文件硬链接文件(不能对目录创建硬链接)

In-s原文件/目录符号链接文件

(2)是否新增文件:硬链接不增文件,符号链接增加文件。

(3)删除原文件/目录

硬链接:对应i节点链接数-1。

符号链接:符号链接文件失效。

(4)删除链接文件

删除硬链接文件,使对应i节点的链接数-1。

删除符号链接文件,对原文件/目录无任何影响

(5)是否跨文件系统:硬链接不可以,符号链接可以

五、编程题

I.编写程序pro3.c,将字符串“helloworld”通过输出重定向方式写入文件fl中

#include<stdio.h>

#include<unistd.h>

#include<fcntl.h>

#include<sys/stat.h>

#include<sys/lypes.h>

main()

intfd;

if((fd=open("f1",O_WRONLY|O_CREAT,()644))==-1)

perror("openfail");

if(dup2(fd,I)=="1)

perror("Redirectfailed");

printf("Helloworld\n");

close(fd);

1

3.实现“ls-1文件名功能”

参考5.6

第6章

一、填空题

I.unlink,文件名和文件i节点的对应关系

2.opendir,closedir,readdir

3.改变当前目录

4.mkdir,rmdir

二、选择题

题号答案

1B

2A

3B

4A

5D

6C

7A

三、编程题

代码略,编程思路:

1-4参考案例5和案例6。

5参考例6-2

6-9需要结合第四章、第五章、第六章内容完成。

第7章

一、选择题

|题号|答案i

nj

nd

DJCACA

二、简答题

1.fork与vfork区别?

(1)fork创建的子进程复制父进程的整个地址空间(或写时复制),vfork不创建这一

副本,子进程借用父进程的地址空间,直到其调用exec族函数或终止;

(2)fork创建的子进程和父进程相互独立地运行,而vfork创建子进程后挂起父进程,

直到子进程终止或调用exec族函数。

2.阅读以下代码,若execlp调用成功的话,“Done!”会打印输出吗?为什么?

#includevstdio.h、

intmain()

(

printfC'Runningpswithexeclp\n^^);

execlp(“ps",”ps'',"-ar'O);

printf("Done!\n");

exit(O);

}

不会输出“Done!”。

原因:

执行execlp("ps”Jpsi-a『,O)调用成功后,当前进程的地址空间被新的程序ps所替代,

将执行“ps-af”

三、编程题

I.使用fork创建进程,在子进程中打印“lamthechild”和子进程pid,在父进程中打印“I

amthefather”和父进程pid

#includc<sys/typcs.h>

#include<stdlib.h>

#include<stdio.h>

inimain()

(

pid_tpid;

pid=fork();

if(pid<0)

(

pcrrorC'fork");

exit(l);

)

elseif(pid==0)

printf("Iamthechild\n°);

else

printf("Iamthefather\n");

exit(0);

)

2.创建子进程,在子进程中执行“ps-A”命令,父进程等待子进程结束后打印“childover”

及所处理的子进程进程号

#include<sys/types.h>

#inckide<stdlib.h>

main()

pid_tpid.cpid;

inti;

char*args[64];

args[O]="ps”;

args[l尸'-A”;

args[2]=NULL;

pid=fork();

if(pid<0)

{

peiror(“fork”);

exit(l);

)

elseif(pid==O)

{

cxccvp(args[O],args);

cxit(O);

1

else

|

cpid=wait(NULLl;

printfflhildover!cpid=%d\n”,cpid);

1

I

第8章

一、选择题

题号答案题号答案

1B7B

2C8C

3A9C

4C10C

5B11C

6C12B

二、编程题

1.编程:由用户键盘输入次数n和字符串sir,要求在新线程中显示n次sir字符串。

#include<pthread.h>

#include<stdio.h>

#includc<stdlib.h>

#include<unistd.h>

structst

(

intn;

charstr[10];

);

void*fun(void*arg)

(

structst*q=(structst*)arg;

while(q->n-)

puts(q->slr);

pthread_exit(O);

)

intmain()

(

pthrcad_ttid;

interr;

structsts;

scanf("%d",&s.n);

scanf("%s",s.str);

err=pthread_create(&tid,NULL,fun,(void*)&s);

if(err)

{

pcrror("pthread_crcate()");

exit(l);

}

pthreadjoin(tid,NULL);

exit(O);

)

2.参考答案:

ThisispthreadI.thesentense1

Thisispthread2.thesentenseI

ThisispthreadI.thesentense2

Thisispthread2.thesentense2

x=H,y=l5

原因:

(1)线程1先运行,线程2后运行。

线程1执行sleep(l);后阻塞,线程2继续执行,线程2执行至ijslecp(l);时线程2阻塞,

线程1阻塞结束继续执行,线程1执行结束后线程继续执行到结束。

(2)线程1和线程2共享进程的数据段,因此共享变量x,%

第9章

一、选择题

题号答案题号答案

1D7C

2B8B

3A9B

4D10A

5A11C

6A

二、简答题

1.进程间通信的6种方式是什么?简述它们的通信原理。

(1)信号:用于通知接收进程有某种事件发生。

<2)管道:连接一个进程的输出至另一个进程的输入的一种方法。

(3)信号量:一个计数器,用来记录对某个资源的使用情况。

(4)共享内存:允许多个进程访问同一块内存空间。

(5)消息队列:消息的链表,链表中每个节点包括消息类型和正文两部分。

(6)套接字:在网络上主机间进程进行通信的方式。

2.简述pipe与FIFO的区别与联系。

pipe为未命名管道,FIFO为命名管道。

联系:pipe和FIFO都是单向传输,一端为读,另一端为写,字符在管道中先进先出。

管道空间在内存中。

区别:pipe只能在有亲缘关系的进程中使用,如父子进程;

FIFO有名字,所以只要知道该名字,无关进程之间也可以使用。

3.什么是信号?说明产生信号的几种方式以及进程X寸信号的处理方式。

信号:软中断,被发送给一个正在执行的进程,通知该进程有某一特定事件发生。

产生信号的方式有:

(I)用户操作。如键盘操作Ctrl-C,最终使得内核产生信号SIGINT。

(2)进程执行出错。如浮点数溢出,内核也会产生信号。

(3)进程执行某个系统调用。如调用kill向某个进程或进程组发送信号。

进程对信号的处理方式有:

忽略,捕捉,执行系统默认动作。

4.说明信号传递的过程。

(1)生成(generating)<,内核要更新目标进程的数据结构,表示一个新的信号已经被

发送给此进程。此时,进程并没有对信号做出任何响应。

(2)传递(delivery)。强迫目标进程对信号做出响应。

三、编程题

1.编写程序处理SIGINT信号,当程序接收到SIGINT信号后输出“SIGINTiscaught”

#include<stdio.h>

#include<signal.h>

voidsignal_handlcr(intsignum)

switch(signum)

(

caseSIGINT:

prinlfC'SIGINTiscaught!\n");

break;

)

}

intmain()

(

signal(SIGINT,signal_handler);

pause();

return0:

)

2.略,参考sigprocmask系统调用。

3.使用PIPE实现父子进程向子进程发送1234567890,子进程接收并显示

#includc<sys/typcs.h>

#include<stdio.h>

main()

(

intpfd⑵;

charbuf[32];

pid_tpid;

pipe(pfd);

if((pid=fork())<0)

perror("fork");

elseif(pid>0)

{

close(pfd[0]);

write(pfdll],"l234567890",11);

}

else

{

close(pfd[l]);

read(pfd[O],buf,ll);

printf("childread:%s\n",buf);

4.略,主要使用FIFO管道实现。

5.略,涉及对SIGALRM信号的捕捉,文件的写入。

6.略,使用FIFO管道实现。

第10章

一、选择题

题号答案

1C

2B

3C

4A

5B

二、编程题

I.利用信号量时限“生产者-消费者”问题

#include<semaphore.h>

#includc<pthrcad.h>

#includc<sld沁.h>

#defineBUFSIZE50

sem_tmutex;

sem_tempty;

scm_tfull;

in(buffer[BUFSIZEl;

intin=0;

intout=0;

intproduction=0;

intconsume=0;

void*producer()

(

while(l){

sem_wail(&empty);

sem_wail(&mutex);

printf("producer%d\nH.production);

buffer[in%BUFSIZE]=production;

production++;

in++;

sem_post(&inutex);

sem_post(&full);

sleep(l);

)

void*consumer()

{

whilc(l){

sem_wail(&full);

sem_wail(&mutex);

consume=buffer[out%BUFSIZE];

out++;

printf("consumer%d\nu,consume);

sem_post(&mutex);

seni_post(&empty);

)

1

voidinit_scms()

{

sem_init(&mutex,O,I);

sem_init(&empty,0,50i;

sem_init(&full,0,0);

)

voiddestroy_scms()

{

scm_dcstroy(&niutcx);

sem_destroy(&emp(y);

sem_destroy(&full);

)

intmain(intargc,char*argv[J)

{

init_sems();

pthread_(proc;

pthread_tcons;

pthread_create(&proc.NULL,producer,NULL);

pthread_create(&cons,NULL,consumer,NULL);

pthrcad_join(proc,NULL);

plhreadJoin(cons,NULL);

destroy_sems();

return0;

)

2.分别利用共享内存和消息队列实现进程Sender向Recesive发送“helloIPC!”。

共享内存方式:

a)接收端

#include<stdio.h>

#includc<stdlib.h>

#include<unistd.h>

#include<string.h>

#include<sys/types.h>

#include<sys/ipc.h>

#includc<sys/shm.h>

#dcfineSHMSIZE4096

intmain(intargc,char*argvfl)

{

intshmid;

kcy_tkey;

void*shmptr;

key=ftok("kcy",l);

if(argc!=2)

{

printf("shmsrvneedsastring.$shmsn?\"123456\"'.n");

return1;

)

if(key==-1)

(

perror("flokfailed");

return-1;

)

shmid=shmget(key,SHMSIZE,IPC_CREAT|IPC_EXCL|0600);

if(shmid==-I)

(

perror("shmgelfailed");

return1;

)

printf("%d\n",shmid);

shmptr=shmat(shinid.0,0);

if(shmptr==(void*)-1)

(

perror("shmaterror");

return1;

niemcpy(shmptr,aigv[1],strlen(argv[I])+1);

if(shmdt(shinptr)==-I)

perror("shmdtfailed");

return1;

I

return0:

I

b)发送端

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<string.h>

#include<sys/types.h>

#include<sys/ipc.h>

#inckide<sys/shm.h>

#dcfincSHMSIZE4096

intmain(intargc,char*argv[])

(

intshmid;

key_tkey;

void*shmptr;

charbuflSHMSIZE];

key=ftokCkey",1);

shmid=shmget(key,SHMSIZE,SHM_R|SHM_W);

iRshmid==-I)

{

perror("shmgelfailed");

return1;

)

shmptr=shmat(shmid.0,0);

if(shmptr==(void*)-1)

{

perror("shmaterror");

return1;

)

inemcpy(buf,shmptr,strlen(shniptr)+1);

printf(M%s\nH,buf);

if(shmdt(shmptr)==-I)

{

perror("shmdtfailed");

return1;

return0;

1

消息队列方式:略。

3.略,使用信号量和共享内存来实现。

第11章

一、选择题

题号答案

1C

2B

3A

4D

5A

6A

7B

二、简答题

1.

文字:

服务器先启动

(1)调用socket函数创建一个套接字so

(2)调用bind函数将s绑定一个地址和端口号。

(3)调用listen函数使s成为一个监听套接字。

(4)调用accep1阻塞等待接收客户端请求,建立与某客户端的连接套接字ns。

(5)通过ns,调用读写函数处理某客户端请求

(6)终止连接ns。

客户端

(1)调用socket函数创建一个套接字si。

(2)填写服务器的地址和端口号。

(3)调用connect函数与服务器建立连接。

(4)调用读写函数与服务器发送或接收数据。

(5)终止连接si。

图不:

|服务24|

TCP套接字通信过程

[socketO]

循

环

文字:

服务器

(1)调用socket函数创建一个套接字So

(2)调用bind函数将s绑定一个地址和端口号。

<3)等待并接收客户端请求。

<4)调用读写函数处理客户端请求

<5)关闭套接字。

客户端

(I)调用socket函数创建一个套接字si。

(2)调用读写函数发送或接收数据给服务器。

<3)关闭套接字。

图示:

UDP套接字通信过程(面向无连接)

3.简述监听套接字和连接套接字的区别。

监听套接字和连接套接字都是由服务器端产生的,监听套接字可以接受来自客户端的连

接请求,socket创建的是主动套接字,listen将主动套接字转换为监听套接字。连接套接字

是由accept返回,作用是与客户端通信。

三、编程题

略,思路:按照TCP套接字通信图示过程完成,服务器根据客户端发来的文件名,查找文

件是否存在,如果存在则读取文件,发送给客户端,客户端接收数据,创建文件,并保存内

容。

第12章

1.使用多线程方式编程完成本章的综合案例。

以卜给出多线程方式完成多客户端与服务器通信的功能,客户端能看到彼此的消息,类

似简易聊天室。

服务器端:

//server.c

#include<stdio.h>

#include<string.h'>

#inckide<stdlib.h>

#include<unistd.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<sys/socket.h>

#include<pthread.h>

#include<time.h>

#includc<fcntl.h>

#includc<sys/typcs.h>

intsockfd;

intcsfd[50];〃客户端的socketfd

intsize=50;〃聊天室的人数最多为5()

char*IP="0.0.00';

shortPORT=1888;

typedefstructsockaddrSA;

voidwritefile(intfd,char*str)(

time_ttl;

structtm*t2;

charwtxtf1001;

tl=tirne(NULL);

t2=localtime(&tl);

sprintf(wtxt,"%d-%d-%d-%d:%d:%d",t2->tm_year+1900,t2->tm_mon+1,t2->tin_mday,t2->tm_ho

ui\t2->tm_min,t2->tm_sec);

sprintf(wtxt,"%s%s\n",wtxt,str);

write(fd.wtxt,strlen(wtxt));

}

voidscndEach(char*insg){

inii;

for(i=0;i<size;i++){

if(csfd[i]!=0){

printf("sendto%d\n,,,csfd[i]);

send(csfd[i],msg,strlen(msg),O);

void*service_thread(void*p){

intsfd=*(int*)p;

intfdfile=open(',./serverlog,,,O_WRONLY|O_CREM'|O_APPEND,()644);

if(fdfile==-l)

pcrror("opcnscrverlog");

printf("pthread=%d\n'\sfd);

while(l){

charbufT100]={};

if(recv(sfd,buf,sizeof(buf),0)<=0){

inti;

for(i=0;i<size;i++){

if(sfd==csfd[i]){

csfd[i]=0;

break;

)

}

printf("exit:sfd=%dquit\n",sfd);

pthread_exit((void*)i);

)

sendEach(buf);

writefile(fdfile,buf);

)

}

intmain(){

intopt=1;

sockfd=so€ket(PFJNET,SOCK_STREAM,0);

setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizcof(opt));

if(sockfd==-1){

perror("creatsocketfaild");

exit(-l);

}

structsockaddr_inaddr;

addr.sin_family=PF_1NET;

addr.sin_port=htons(PORT);

addr.sin_addr.s_addr=inet_addr(IP);

if(bind(sockfd,(SA*)&addr,sizeof(addr))==-1){

perror(ubindfaild");

exit(-l);

if(listen(sockfdJOO)==-1){

pcrror("setlistenfaild");

exit(-l);

}

printf("ser\?erstart!\n");

while(1){

structsockaddr_infromaddr;

socklen_llen=sizeof(fromaddr);

intconnfd=accept(sockfdXSA*)&fromaddr,&lcn);

if(connfd==-!){

printf("clientconnectfaild...\n");

continue;

)

inti=0;

for(i=0;i<

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论