linux期末大报告.docx
- 文档编号:3732737
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:21
- 大小:241.33KB
linux期末大报告.docx
《linux期末大报告.docx》由会员分享,可在线阅读,更多相关《linux期末大报告.docx(21页珍藏版)》请在冰豆网上搜索。
linux期末大报告
Linux程序设计
期末大作业报告
学院:
专业:
年级:
级
学生姓名:
学生学号:
任课教师姓名:
任课教师职称:
讲师
摘要
●对linux的简单认识
操作系统是计算机最重要的系统软件,是计算机应用的基础.Unix系统是迄今为止最优秀的操作系统,虽历经几十年,有许多变化,但基本的体系结构保持稳定。
Linux是一种自由和开放源码的类Unix操作系统。
目前存在着许多不同的Linux,但它们都使用了Linux内核。
Linux可安装在各种计算机硬件设备中,从手机、平板电脑、路由器和视频游戏控制台,到台式计算机、大型机和超级计算机。
Linux是一个领先的操作系统,世界上运算最快的10台超级计算机运行的都是Linux操作系统。
●作业简要概述
本课程大作业共有两个题,一个是shell编程,如实现自己模拟shell下的cd、ls指令等,要求说明程序主要功能,每行给出注释;另一题是一个二选一,选择了简单的聊天室程序设计,该题要求设计并实现简单的聊天室程序,可以是终端字符界面,支持用户管理,用户名/密码注册和登录,客户端登陆到服务器聊天后,可以在聊天室内与其他用户交流(这个聊天室中的任何一个用户输入一段字符后,室内的其他用户都可以看到这句话)。
据此,聊天程序分为客户端和服务器端。
客户端对应每一个参加聊天的用户,完成从终端上输入采集并传递到服务器端和从服务器端接收信息输出显示的功能。
在实验报告中针对代码给出了对应的注释和自己的理解。
关键字:
Linux;shell编程;聊天室程序
一、期末大作业的目的
《Linux程序设计》大作业是在完成理论课程学习之后,通过大作业的方式对学生进行综合实践考核,在学生掌握Linux的基本编程知识及常用的操作命令基础上,提高学生对所学知识的应用能力,特别是:
煅炼学生搜集有关Linux资料,在资料文档的帮助下,运用Linux的基本知识及常用的操作命令来解决问题的能力。
二、大作业的基本要求
要求能完成给定的编程任务,并写出相应的大作业总结报告
2.1、根据合理的进度安排,按照程序的流程及方法,踏实地完成期末大作业的任务安排。
2.2、按照任务要求,完成各个功能模块的功能划分和程序编写,调试代码并运行。
2.3、按要求撰写大作业报告。
三、大作业内容
1、作业题目一
要求:
写出2个Shell程序,每个不少于15行(如实现自己模拟shell下的cd、ls指令等),说明程序主要功能,每行给出注释;
shell编程1
●实现test命令的功能:
在if-then语句中声明test命令的另一种方法(如果条件为真,则返回0;如果为假,则返回一个大于0的值):
if[condition](注意condition前后都要有空格)
then
command
fi
test命令能够实现三类评估:
数值比较、字符串比较和文件比较。
以下先对每一种比较做出说明:
1.数值比较
n1-eqn2检查n1是否等于n2
n1-nen2检查n1是否不等于n2
n1-gen2检查n1是否大于或等于n2
n1-gtn2检查n1是否大于n2
n1-len2检查n1是否小于或等于n2
n1-ltn2检查n1是否小于n2
2.字符串比较
可以检查将要对其操作的字符串是否存在、是否相同或者是否不同。
51Testing软件测试网;D-@hXiL.nf7C[
(kn-nB-|2N2L,Dn0String测试以判断字符串是否不为空
$MU,f7|%hSbg0-nstring测试以判断字符串是否不为空;字符串必须为test所识别
RY/O?
qwP/g?
0-zstring测试以判断字符串是否为空;字符串必须为test所识别
51Testing软件测试网8`v3QM+XC
string1=string2测试以判断string1是否与string2相同
p
wIbGL(D}W#q0string1!
=string2测试以判断string1是否与string2不同
g0U'j7^-@wZ,]bY051Testing软件测试网ixf#iT#XUf+d
3.文件比较
-bfile如果文件为一个块特殊文件,则为真
51Testing软件测试网6s?
0y;ys9xsL
-cfile如果文件为一个字符特殊文件,则为真
51Testing软件测试网4m-o\pIR
-dfile如果文件为一个目录,则为真
Sr:
V\3J0-efile如果文件存在,则为真
51Testing软件测试网8]uapDC"[
-ffile如果文件为一个普通文件,则为真
51Testing软件测试网9^1h\!
m[\?
l
-gfile如果设置了文件的SGID位,则为真
51Testing软件测试网@%`_U3X`
-Gfile如果文件存在且归该组所有,则为真
+C2dL%yR1g_0-kfile如果设置了文件的粘着位,则为真
51Testing软件测试网p[3B[4_HNCf
-Ofile如果文件存在并且归该用户所有,则为真
51Testing软件测试网Mm.\"L0A%BU
-pfile如果文件为一个命名管道,则为真
:
Y[-L"Y[0-rfile如果文件可读,则为真
51Testing软件测试网7P8L(N@z8b9G%X_r0H
-sfile如果文件的长度不为零,则为真
7Q9j{4T/_Ta0-Sfile如果文件为一个套接字特殊文件,则为真
To8M4z_0-tfd如果fd是一个与终端相连的打开的文件描述符(fd默认为1),则为真
!
yI)i;b!
Z#DH7}#~8[
sa0-ufile如果设置了文件的SUID位,则为真
51Testing软件测试网)l9\"pK8})Rp6C\Q
t
-wfile如果文件可写,则为真51Testing软件测试网sQt(Vr'u
mD#l(j
-xfile如果文件可执行,则为真
以下为实现test的shell程序:
o$J(i;sJ*B8KP051Testing软件测试网NM9g1Bf:
I!
B
j6o
#!
/bin/sh#对shell的声明,指明shell的路径,如果没有该声明,那么脚本将在默#认路径下执行
#unload-programtobackupandremovefiles
#syntax:
unloaddirectory除了第一行#!
/bin/sh外其他出现#为注释部分
#checkarguments#数值比较
if[$#-ne1]#测试传递给shellscript的参数个数是否不等于1
then
echo"usage:
$0directory"#输出当前shell程序的名称
exit1#这次执行if函数返回1
fi#条件语句结束
#checkforvaliddirectoryname文件比较
if[!
-d"$1"]#测试$1是否为一个文件目录,不是则为真
then
echo"$1isnotadirectory"
exit2#执行该次if函数返回2
fi
cd$1#打开$1目录
ls-a|cpio-o>/dev/rmt/0h#完成数据的备份,成功则返回0
if[$?
-eq0]#测试上一个命令的返回代码是否等于0,如果为真则执行以下
then
rm-rf*#删除文件
else
echo"Aproblemhasoccuredincreatingbackup"#如果上一条判断结果为假,就输
#出这三条信息
echo"Thedirectorywillnotbeereased"
echo"Pleasecheckthebackupdevice"
exit3#返回值为3
fi
#endofunload
补充上述代码中的一些特殊shell符号的含义:
$#表示传递给shellscript的参数个数
$0当前shell的名称
$n(n:
1-)位置参数
$?
上一个命令的返回代码
运行结果阐述:
该shell程序实现了test命令对数值和文件的比较,方法为[$#-ne1]、[!
-d"$1"]和[$?
-eq0],当系统接收到一个shell脚本时([$#-ne1]),就去测试它是否为一个目录([!
-d"$1"]),接着打开该目录文件,完成数据备份,备份成功后有执行删除命令,失败则输出错误信息。
shell编程2
●通过两个变量($*和$@)实现对命令行参数的迭代:
变量“$*”将所有的参数视为一个单词
变量“$@”将分别看待每一个参数
#!
/bin/sh#对shell的声明,指明shell的路径
a=1#定义一个变量a并初始化为1
forparam1in"$*"#定义,运用for循环迭代$*变量
do
echo"\$*parameter#$a=$param1"#将输入的参数传给$*变量
a=$[$a+1]#根据输入的内容不断更改a的值
done#循环结束
b=1#定义一个变量b并初始化为1
forparam2in"$@"#定义$@变量,运用for循环迭代$@变量
do
echo"\$#parameter#$b=$param2"#将输入的参数传给$*变量
b=$[$b+1]#根据输入的内容不断更改b的值
done#循环结束
c=1
forparam3in"$#"#定义$#变量,$#变量表示传给shellscript的参数个数
do
echo"thetotalcounts=$param3"#输出shellscript接收到的参数的个数
c=$[$c+1]
done循环结束
程序运行结果如图:
根据运行结果很直观的看到了shell编程中$*、$@和$#的功能。
这个例子用例for循环语句实现变量的迭代。
程序参照网络,通过对代码和变量用法的解读,收获很大。
2、作业题目二
要求:
设计并实现一个简单的聊天室程序,可以是终端字符界面,支持用户管理,用户名/密码注册和登录,客户端登陆到服务器聊天后,可以在聊天室内与其他用户交流(这个聊天室中的任何一个用户输入一段字符后,室内的其他用户都可以看到这句话)。
据此,聊天程序分为客户端和服务器端。
客户端对应每一个参加聊天的用户,完成从终端上输入采集并传递到服务器端和从服务器端接收信息输出显示的功能。
程序代码
●服务端的实现,文件名为“server.c”:
//server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#definePERMS_IRUSR|S_IWUSR
#defineMYPORT13000//宏定义定义通信端口
#defineBACKLOG10//宏定义,定义服务程序可以连接的最大客户数量
#defineWELCOME"@@@@@@@@@@@@-Welcometothechatroom!
-@@@@@@@@@@@@"/*宏定义,当客户端连接服务端时,就在客户端显示此信息*/
//1.转换函数,将int类型转换成char类型
voiditoa(inti,char*string)
{
intpower,j;
j=i;
for(power=1;j>=10;j/=10)
power*=10;
for(;power>0;power/=10)
{
*string++='0'+i/power;
i%=power;
}
*string='\0';
}
//2.获取当前系统时间
voidget_cur_time(char*time_str)
{
time_ttimep;
structtm*p_curtime;
char*time_tmp;
time_tmp=(char*)malloc
(2);
memset(time_tmp,0,2);//将time_tmp指针数组里的前面2位置为0
memset(time_str,0,20);//将time_str[20]清零
time(&timep);//得到timep里的值,即time_t方法获得的时间
p_curtime=localtime(&timep);//得到tm结构体中的时间是已经被转化为本地时间
strcat(time_str,"(");/*strcat函数将参数“(”字符串拷贝到time_str所指的字符串尾,并且返回time_str字符串的起始地址*/
itoa(p_curtime->tm_hour,time_tmp);//将整型转换为字符型,对应的小时/分/秒
strcat(time_str,time_tmp);/*将time_tmp指针数组中(以后的字符串拷贝到time_str所指的字符串尾部,并返回time_str字符串的起始地址*/
strcat(time_str,":
");
itoa(p_curtime->tm_min,time_tmp);
strcat(time_str,time_tmp);
strcat(time_str,":
");
itoa(p_curtime->tm_sec,time_tmp);
strcat(time_str,time_tmp);
strcat(time_str,")");//将)拷贝到time_str中并返回time_str的起始地址
free(time_tmp);//释放time_tmp指针
}
//3.创建通信时所需的共享存储区
key_tshm_create()
{
key_tshmid;//定义一个共享存储区的标志
//shmid=shmget(IPC_PRIVATE,1024,PERM);
if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1)/*创建一个共享内存区,如果失败则返回-1,打印CreateShareMemoryError:
%s\n\a*/
{
fprintf(stderr,"CreateShareMemoryError:
%s\n\a",strerror(errno));
exit
(1);
}
returnshmid;//成功则返回新建共享内存的id
}
//4.创建套接字,并将地址绑定到端口上,地址包括主机和端口(获得电话线)
intbindPort(unsignedshortintport)//给电话线分配号码
{
intsockfd;//套接字
structsockaddr_inmy_addr;
sockfd=socket(AF_INET,SOCK_STREAM,0);/*创建一个基于数据流的套接字:
支持ARPAInternet地址格式;套接口类型为TCP;没有指定套接口所用协议*/
my_addr.sin_family=AF_INET;//IPv4协议族
my_addr.sin_port=htons(port);/*将主机的无符号短整型数(端口号)转换成网络字节顺序*/
my_addr.sin_addr.s_addr=INADDR_ANY;//按照网络字节存储ip地址
bzero(&(my_addr.sin_zero),0);
if(bind(sockfd,(structsockaddr*)&my_addr,sizeof(structsockaddr))==-1)
/*将套接字和主机号绑定在一起,成功返回0并打印"bingsuccess!
",失败返回-1*/
{
perror("bind");
exit
(1);
}
printf("bingsuccess!
\n");
returnsockfd;//绑定成功并返回套接字sockfd
}
intmain(intargc,char*argv[])
{
intsockfd,clientfd,sin_size,recvbytes;//定义监听套接字、客户套接字
pid_tpid,ppid;//定义父线程(pid)和子线程(ppid)标记变量
char*buf,*r_addr,*w_addr,*temp,*time_str;//="\0";//定义一个临时存储区
structsockaddr_intheir_addr;//定义地址结构
key_tshmid;//定义共享区的id,从#include
shmid=shm_create();//创建共享存储区
temp=(char*)malloc(255);/*为temp变量分配一个大小为255个char类型所占内存,然后将这个空间转换成一个字符指针,就是数组,数组首地址复制给temp*/
time_str=(char*)malloc(20);
sockfd=bindPort(MYPORT);//调用BindPort()函数绑定端口
while
(1)
{
if(listen(sockfd,BACKLOG)==-1)/*在sockfd(已经绑定了端口的套接字)上监听(允许接入调用),相当于用一只耳朵来听*/
{
perror("listen");
exit
(1);
}
printf("listening......\n");
if((clientfd=accept(sockfd,(structsockaddr*)&their_addr,&sin_size))==-1)/*接收客户端连接的定义,当客户提出申请时套接字和地址要与服务器定义的一致,
这一过程相当于听到电话铃响后接起了电话*/
{
perror("accept");
exit
(1);
}
printf("acceptfrom:
%d\n",inet_ntoa(their_addr.sin_addr));
send(clientfd,WELCOME,strlen(WELCOME),0);//发送通信信息
buf=(char*)malloc(255);
ppid=fork();//连接成功以后创建一个子进程用于管理信息的收发
if(ppid==0)
{
//printf("ppid=0\n");
pid=fork();//创建子进程,即ppid
while
(1)
{
if(pid>0)/*父进程用于接收信息,当pid>0表示有客户段接入到了服务器。
当客户端向服务器提出连接请求成功后就复制一个子进程,每一个子进程作为一个客户*/
{
memset(buf,0,255);//将缓冲区清零
//printf("recv\n");
//sleep
(1);
if((recvbytes=recv(clientfd,buf,255,0))<=0)/*从套接口接收数据:
数据来自客户端套接字,将数据存在用于接收数据的缓冲区,缓冲区长度为255*/
{
perror("recv1");
close(clientfd);
raise(SIGKILL);
exit
(1);
}
//将共享区内的数据存入缓冲区内:
w_addr=shmat(shmid,0,0);/*把共享内存区域映射到调用进程的地址空间中,这样进程就可以方便地对共享区域进行访问操作*/
memset(w_addr,'\0',1024);
strncpy(w_addr,buf,1024);//将地址空间内的数据拷贝到缓冲区中
get_cur_time(time_str);//获取系统当前时间
strcat(buf,time_str);//将时间也写入缓冲区内
printf("%s\n",buf);//显示聊天内容和时间
}
elseif(pid==0)//子进程用于发送信息
{
//scanf("%s",buf);
sleep
(1);
r_addr=shmat(shmid,0,0);/*把共享内存区域映射到调用进程的地址空间中,这样进程就可以方便地对共享区域进行访问操作*/
//printf("---%s\n",r_addr);
//printf("cmp:
%d\n",strcmp(temp,r_addr));
if(strcmp(temp,r_addr)!
=0)//比较共享存储区和进程的地址空间内容
{
strcpy(temp,r_addr);/*内容不一致则把共享存储区里的字符串拷贝到进程的地址空间中*/
get_cur_time(time_str);
strcat(r_addr,time_str);//将时间也拷贝到进程的地址空间里面
//printf("discriptor:
%d\n",clientfd);
//if(send(clientfd,buf,strlen(buf),0)==-1)
if(send(clientfd,r_addr,strlen(r_addr),0)==-1)/*子进程用于发送信息*/
{
perror("send");
}
memset(r_addr,'\0',1024);//将进程的地址空间清零
strcpy(r_addr,temp);//把进程的地址空间内的字符串拷贝到共享区中
}
}
else
perror("fork");
}
}
}
printf("@@@@@@@@@@@@@@-thetalkisover-@@@@@@@@@@@@\n");
free(buf);//释放用于存储接收数据的缓冲区
close(sockfd);//关闭服务端套接字,相当于挂断
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 期末 大报