资源描述
实验1 RedHat Linux常用命令使用
【实验目的】
1、 了解linux的基本命令,熟练掌握其基本操作;
2、 掌握一些常用的Linux命令的使用方法。
【实验要求】
1、 了解RedHat Linux获得的方法以及怎样在虚拟机上进行安装;
2、 复习一些常用Linux命令的使用方法,掌握其功能和使用时的选项和参数。
【实验步骤】
一、RedHat Enterprise Linux 4的启动
启动VMWare虚拟机,即可看到Linux的启动画面,实验室的root密码统一设定为123456。
二、常用的Linux命令使用
启动到Linux界面以后,在桌面上右键打开终端,即可进入命令输入的终端界面。
请在实验过程中输入正确的命令和选项参数,完成以下功能:
1:创建自己的账户(如:test)和口令。
2:使用新创建的用户账户和口令登录Linux系统,察看登录后的界面。
3:使用pwd命令察看当前的工作目录,然后用ls命令查看当前目录下的内容,尝试使用-a,-l,-F,-A,-lF等不同选项并比较不同之处。
4:在当前目录下建立一个名为test的新目录,然后将工作目录切换到test下,尝试将/etc目录下的文件passwd拷贝到该目录下(cp源文件 目的目录)。察看当前目录下的passwd文件的属主和文件权限。
5:尝试向当前目录下的passwd文件和/etc/passwd文件分别写入一些新内容(可使用 echo "字符串" >>文件 的命令),看看操作能否成功,如果不能成功,请说明原因。用cat命令浏览文件password的内容,用more命令进行浏览翻页操作,再用less命令浏览文件的内容。比较这几个命令的不同之处
6:用ls命令查看test下文件的权限,用mv命令更改文件password的文件名为test.txt,尝试用chown和chgrp更改文件的属主为root、组为root,看看能否成功,不成功,请说明原因。尝试用chmod将文件权限为"-rw-------"。看看能否成功,不成功,请说明原因。
7:用rm命令删除test目录下的所有文件,再用rmdir命令删除test目录。
(想一想有没有一条命令将目录及目录下的所有文件删除,写出这条命令)。
8:使用ps命令查看当前系统内的进程,并利用man命令获取ps命令的参数,写出获取当前终端进程执行情况的ps命令。
9:使用df命令查看当前系统已安装的文件系统的空间使用情况,记录结果。
10:使用man获取tar和gzip的帮助信息,尝试将test目录下的文件打包并压缩,然后到另外一目录tmp下解包,写出这几条命令。
11:尝试执行"ls –l /tmp",看看这条命令的执行会出现什么结果,解释一下这条命令。
12:执行cal和date命令,说说这两条指令的用途。
13:执行命令clear和logout,退出系统。(想一想有没有其他的方法,写出这种方法)
14:用ifconfig命令查看网卡的IP地址和MAC地址。
15:执行命令ftp ,使用用户名anonymous和空密码登录,将目录切换到/linux,下载压缩包linux-2.6.10.tar.bz2并解压到当前目录。
实验2 Linux文本编辑、Shell编程与网络服务配置
【实验目的】
1、 学习Linux常用编辑器的使用;
2、 学习Linux下Shell编程的基本方法;
3、 练习网络服务的配置和管理。
【实验要求】
1、 复习vi编辑器的使用方法,学习gedit和emacs的使用;
2、 复习网络配置和网络服务器的配置和使用的内容。
【实验步骤】
一、shell编程
1. 利用vi编辑器编写一个shell脚本程序filemenu:
until
echo List Directory..........1
echo Change Directory........2
echo Edit File...............3
echo Remove File.............4
echo Exit Menu...............5
read choice
test $choice = 5
do
case $choice in
1) ls;;
2) echo Enter target directory
read dir
cd $dir
;;
3) echo Enter file name
read file
vi $file
;;
4) echo Enter file name
read file
rm $file
;;
q|Q|5) echo Goodbye;;
*) echo illegal Option
esac
2. 调试该程序使其能正常工作,运行之。解释这个程序的功能。
二、网络服务配置与管理
1. 网络文件系统(NFS,NetworkFileSystem)是一种将远程主机上的分区(目录)经网络挂载到本地系统的一种机制,通过对网络文件系统的支持,用户可以在本地系统上像操作本地分区一样来对远程主机的共享分区(目录)进行操作。
2.Linux NFS服务器的配置
以root身份登陆Linux服务器,编辑/etc目录下的共享目录配置文件exports,指定共享目录及权限等。
编辑文件/etc/exports,在该文件里添加如下内容:/home/test 192.168.1.*(rw, sync, no_root_squash)然后保存退出,目录/home/test可改为自选的共享目录。
添加的内容表示:允许ip地址范围在192.168.1.*的计算机以读写的权限来访问/home/test目录。/home/test也称为服务器输出共享目录。括号内的参数意义描述如下:rw:读/写权限,只读权限的参数为ro;sync:数据同步写入内存和硬盘,也可以使用async,此时数据会先暂存于内存中,而不立即写入硬盘。no_root_squash:NFS服务器共享目录用户的属性,如果用户是root,那么对于这个共享目录来说就具有root的权限。
接着执行如下命令,启动端口映射: /etc/rc.d/init.d/portmap start
最后执行如下命令启动NFS服务,此时NFS会激活守护进程,然后就开始监听Client端的请求: /etc/rc.d/init.d/nfs start
我们可以进行NFS服务器的回环测试,验证共享目录是否能够被访问。在Linux服务器上运行如下命令:
mkdir /mnt/nfs
mount–tnfs 192.168.1.120:/home/test /mnt/nfs (此命令使用的本机IP地址请使用ifconfig命令查看)
ls /mnt/nfs
如果NFS正常工作,应该能够在/mnt/nfs目录看到/home/test共享目录中的内容。
拆卸NFS文件系统的命令 umount /mnt/nfs 。
3.NFS客户端的配置
在Linux服务器设置好后,还需要对客户端进行相关配置。此项任务可以相邻的两台计算机互相完成。
mount–tnfs 192.168.1.120:/home/test /mnt/nfs (此命令使用的本机IP地址请使用相邻计算机的IP地址)。
此时,目标系统端所显示的内容即为Linux服务器的输出目录的内容,即Linux服务器的输出目录/home/test通过NFS映射到了目标系统的/mnt/nfs目录。用户可以用增/删/修改文件的方式来验证实际效果。
选作:telnet服务器配置
1. 以root身份登陆Linux服务器,编辑/etc/xinetd.d/telnet (或krb5-telnet),找到 disable = yes 将 yes 改成 no 。
2.激活服务: service xinetd restart
3.测试服务: 在windows主机的命令行下输入telnet 虚拟机ip,如果配置正确,系统提示输入远程机器的用户名和密码
Login:
PassWord:
注:默认只允许普通用户
4.telnet服务限制
telnet是明文传送口令和数据的,如果你对其默认的设置不满意,有必要对其服务范围进行限制。假设你的主机的ip是210.45.160.17,就可以按如下方式设置了。
#vi /etc/xinetd.d/telnet
service telnet
{
disable = no #激活 telnet 服务,no
bind = 210.45.160.17 #your ip
only_from = 210.45.0.0/16 #只允许 210.45.0.0 ~ 210.45.255.255 这个网段进入
only_from = #只有教育网才能进入!
no_access = 210.45.160. #这两个ip不可登陆
access_times = 8:00-12:00 20:00-23:59 # 每天只有这两个时间段开放服务
......
}
5.telnet root用户的登入
telnet不是很安全,默认的情况之下不允许root以telnet进入Linux主机。若要允许root用户登入,可在普通用户进入后,切换到root用户,拥有root的权限。
实验3 Linux开发工具的使用
【实验目的】
1、 学习gcc的编译方法与使用;
2、 学习Linux调试器GDB的使用学习Linux内核编译的方法。
3、学习编写makefile文件来进行工程项目管理
【实验要求】
1、 复习gcc的编译选项和gdb的调试命令;
2、 复习makefile文件的编写方法。
【实验步骤】
一、编译器gcc的使用
1. 编辑一个C语言程序文件hello.c:
#include <stdio.h>
main()
{
char name[20];
printf(“Please input your name:”);
scanf(“%s”,name);
printf(“Welcome %s!\n”,name);
return 0;
}
2. 编译文件: gcc –o hello hello.c。
3. 如果有错误,修改hello.c的内容,然后再次编译,直至没有错误为止。
二、用GDB调试程序BUG
1. 使用文本编辑器输入以下代码greet.c。程序试图倒序输出main函数中定义的字符串,但结果没有显示。
#include <stdio.h>
int display1(char *string);
int display2(char *string);
main()
{
char string[] = “Welcome to Linux!”;
display1(string);
display2(string);
}
int display1(char *string)
{
printf(“The original string is %s \n”,string);
}
int display2(char *string1)
{
char *string2;
int size,i;
size = strlen(string1);
string2 = (char *)malloc(size + 1);
for(i=0;i<size;i++)
{
string2[size-i] = string1[i];
}
string2[size+1]=’ ‘;
printf(“The string afterward is %s\n”,string2);
}
2.使用gcc –g的选项编译这段代码,运行生成的可执行文件,观察运行结果。
3.使用gdb调试程序,通过设置断点、单步跟踪,一步步找出错误所在。
4.纠正错误,更改源程序并得到正确的结果。
三、编写包含多个文件的makefile
1. 利用编辑器编写两个C语言程序:
hello.c
#include “hello.,h”
int main()
{
printf(“Hello everyone!\n”);
}
hello.h
#include <stdio.h>
2. 编辑makefile,如下所示:
hello:hello.c hello.h
gcc hello.c –o hello
3. 键入 make ,查看结果。
4. 重新编辑makefile,如下所示:
OBJS := hello.o
CC := gcc
hello:$(OBJS)
$(CC) $^ -o $@
5. 键入 make ,查看结果。
实验4 Linux内核编译
【实验目的】
1、 深入理解Linux内核的组织构成;
2、 学习Linux内核编译的方法。
【实验要求】
1、 复习makefile文件的编写方法;
2、 学习Linux内核编译的方法,尝试使用Linux内核版本升级。
一、Linux 内核编译
1.使用 uname –rm 或 uname –a 命令查看当前系统的Linux内核版本。
2. 使用ftp命令在上下载内核压缩包linux-2.6.10.tar.bz2并解压到当前目录。
tar –jxvf linux-2.6.10.tar.bz2
cd linux-2.6.10
3.make mrproper 把原来编译产生的垃圾删除
4.配置内核可以根据需要与爱好使用下面命令中的一个:
make config (基于文本的最为传统的配置界面)
make menuconfig (基于文本选单的配置界面)
make xconfig (基于图形窗口模式的配置界面)
make oldconfig (如果只想在原来内核配置的基础上修改一些小地方,会省去不少麻烦)
进行配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。例如,如果需要内核支持DOS分区的文件系统,则要在文件系统部分选择FAT或DOS系统支持;系统如果配有网卡、PCMCIA卡等,需要在网络配置中选择相应卡的类型。
选择相应的配置时,有三种选择,它们分别代表的含义如下:
“Y”- 将该功能编译进内核
“N”- 不将该功能编译进内核
“M”- 将该功能编译成可以在需要时动态插入到内核中的模块。
将与核心其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响。许多功能都可以这样处理,例如像上面提到的网卡的支持、对FAT等文件系统的支持。
5. make dep (确保关键文件在正确的位置)
这一项在Linux内核2.5.*-2.6.0都不需要了。其实2.4.*某些内核也不需要了。
6. make clean (确保所有有关文件都处于最新版本状态)
7. make zImage (编译压缩形式的内核)
在需要内核支持较多的外设和功能时,内核可能变得很大,此时可以编译大内核:
make bzImage
编译的时间与机器的硬件条件及内核的配置等因素有关,所获得的内核的位置在./arch/i386/boot目录下,当然这里假设用户的CPU是x86型的。
8.如果选择了可加载模块,编译完内核后,要对选择的模块进行编译:
make modules (编译选择的模块)
make module_install (将编译后的模块转移到系统标准位置)
9. make install
上面的命令"make install"将:
(1)把压缩内核映象拷贝到/boot目录下, 并创建相应的System.map符号链接;
(2)修改bootloader的配置文件;
(3)调用mkinitrd程序创建内核的initrd映象.
10. 用编辑器查看/boot/grub/grub.conf配置文件,将其中的hiddenmenu行加上注释标志#
11. 重新启动Linux系统,注意观察启动后出现的菜单选择项,选择刚编译好的新内核启动。
12.启动完成后,使用 uname –rm 或 uname –a 命令查看当前系统的Linux内核版本。
实验5 文件系统编程
【实验目的】
1、 学习Linux对文件系统的操作方法,掌握编程对文件进行操作的方法;
2、 学习Linux下proc文件系统的特殊用途,学会利用其查看系统信息。
【例程】
1、 学习编写C语言程序来对文件系统进行操作;
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int fd1,fd2,fd3,nbytes;
int flags = O_CREAT|O_TRUNC|O_WRONLY;
char buf[10];
if((fd1 = open("rdwr.c",O_RDONLY,0644)) < 0)
{
perror("open rdwr.c");
exit(EXIT_FAILURE);
}
if((fd2 = open("/dev/null",O_WRONLY)) < 0)
{
perror("open /dev/null");
exit(EXIT_FAILURE);
}
if((fd3 = open("/tmp/foo.bar",flags,0644)) < 0)
{
perror("open /tmp/foo.bar");
close(fd1);
close(fd2);
exit(EXIT_FAILURE);
}
while((nbytes = read(fd1,buf,10)) > 0)
{
if(write(fd2,buf,10) < 0)
perror("write /dev/null");
if(write(fd3,buf,nbytes) < 0)
perror("write /tmp/foo.bar");
write(STDOUT_FILENO,buf,10);
}
close(fd1);
close(fd2);
close(fd3);
exit(EXIT_SUCCESS);
}
2、 学习proc文件系统的使用方法。
【实验步骤】
一、Linux文件编程
1.从一个文件中读取最后10KB数据并复制到另一个文件,注意观察缓存大小OFFSET对运行效率的影响
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFFER_SIZE 1024
#define SRC_FILE_NAME "src_file"
#define DEST_FILE_NAME "dest_file"
#define OFFSET 10240
int main()
{
int src_file,dest_file;
unsigned char buff[BUFFER_SIZE];
int real_read_len;
src_file = open(SRC_FILE_NAME,O_RDONLY);
dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,644);
if(src_file < 0 || dest_file < 0)
{
printf("Open file error!\n");
exit(1);
}
lseek(src_file,-OFFSET,SEEK_END);
while((real_read_len = read(src_file,buff,sizeof(buff))) > 0)
{
write(dest_file,buff,real_read_len);
}
close(dest_file);
close(src_file);
return 0;
}
2. 编译、调试该程序使其能正常工作,运行之。解释这个程序的功能。
二、proc文件系统编程
1. /proc --- 一个虚拟文件系统
/proc 文件系统是一种内核和内核模块用来向进程 (process) 发送信息的机制 (所以叫做 /proc)。这个伪文件系统让你可以和内核内部数据结构进行交互,获取有关进程的有用信息,在运行中改变设置。与其他文件系统不同,/proc 存在于内存之中而不是硬盘上。proc 文件系统可以被用于收集有用的关于系统和运行中的内核的信息。
2.下面是一些重要的文件:
/proc/cpuinfo - CPU 的信息 (型号, 家族, 缓存大小等)
/proc/meminfo - 物理内存、交换空间等的信息
/proc/mounts - 已加载的文件系统的列表
/proc/devices - 可用设备的列表
/proc/filesystems - 被支持的文件系统
/proc/modules - 已加载的模块
/proc/version - 内核版本
/proc/cmdline - 系统启动时输入的内核命令行参数
有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。
3.通过 /proc 中可读写的文件提供了对内核的交互机制。写这些文件可以改变内核的状态。大部分 /proc 的文件是只读的,/proc/sys 目录存放所有可读写的文件的目录,可以被用于改变内核行为, /proc/sys/kernel 目录包含反通用内核行为的信息。
例如:
$ hostname
$ cat /proc/sys/kernel/hostname
machinename
$ echo "new-machinename" > /proc/sys/kernel/hostname
$ hostname
new-
以上例子演示了如何修改本机的主机名。
4. 使用C语言编写一个主机信息输出程序,使用open、close、read等系统调用读取不同的proc文件,获得主机信息,然后输出出来。
选作:利用write系统调用修改内核信息并验证。
三、使用fcntl函数实现文件锁
1.编写一个文件lock_set.c,该程序利用fcntl函数实现了一个lock_set函数,该函数实现文件锁功能,F_RDLCK为读锁,F_WRLCK为写锁,F_UNLCK为解锁。
int lock_set(int fd,int type)
{
struct flock old_lock,lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = type;
lock.l_pid = -1;
fcntl(fd,F_GETLK,&lock);
if(lock.l_type != F_UNLCK)
{
if(lock.l_type == F_RDLCK)
printf("Read lock already set by %d\n",lock.l_pid);
else if(lock.l_type == F_WRLCK)
printf("Write lock already set by %d\n",lock.l_pid);
}
lock.l_type = type;
if((fcntl(fd,F_SETLKW,&lock)) < 0)
{
printf("Lock failed:type = %d\n",lock.l_type);
return 1;
}
switch(lock.l_type)
{
case F_RDLCK:
printf("Read lock set by %d\n",getpid());
break;
case F_WRLCK:
printf("Write lock set by %d\n",getpid());
break;
case F_UNLCK:
printf("Release lock set by %d\n",getpid());
return 1;
break;
default:
break;
}
return 0;
}
2.编写一个文件read_lock.c,该文件调用lock_set函数对文件hello上读锁。
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
int fd;
fd = open("hello",O_RDWR|O_CREAT,0644);
if(fd<0)
{
printf("Open file error.\n");
exit(1);
}
lock_set(fd,F_RDLCK);
getchar();
lock_set(fd,F_UNLCK);
getchar();
close(fd);
exit(0);
}
3.编写一个文件write_lock.c,该文件调用lock_set函数对文件hello上写锁。
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
int fd;
fd = open("hello",O_RDWR|O_CREAT,0644);
if(fd<0)
{
printf("Open file error.\n");
exit(1);
}
lock_set(fd,F_WRLCK);
getchar();
lock_set(fd,F_UNLCK);
getchar();
close(fd);
exit(0);
}
四、使用select函数实现多个文件的读写
1.编写如下程序,该程序利用select函数同时对文件in1、in2和标准输入文件进行读操作。当从标准输入文件读到字母q或Q时退出。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#define MAX_BUFFER_SIZE 1024
#define IN_FILES 3
#define TIME_DELAY 60
#define MAX(a,b) ((a>b)?(a):(b))
int main(void)
{
int fds[IN_FILES];
char buf[MAX_BUFFER_SIZE];
int i,res,real_read,maxfd;
struct timeval tv;
fd_set inset, tmp_inset; // fd set
fds[0] = 0;
if((fds[1] = open("in1", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in1 error.\n");
return 1;
}
if((fds[2] = open("in2", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in2 error.\n");
return 1;
}
maxfd = MAX(fds[1],fds[2]);
FD_ZERO(&inset); // clear fd set
for(i=0;i<IN_FILES;i++)
FD_SET(fds[i],&inset); // add fds into fd set
// FD_SET(0,&inset);
tv.tv_sec = TIME_DELAY;
tv.tv_usec = 0;
while(FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset) || FD_ISSET(fds[2], &inset)) // in the fd set or not
{
tmp_inset = inset; // backup the fd set
res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv); // read fd set
switch(res)
{
case -1:
{
printf("Select error\n");
return 1;
}
break;
case 0:
{
printf("Time out\n");
return 1;
}
break;
default:
for(i=0;i<IN_FILES;i++)
{
if(FD_ISSET(fds[i], &tmp_inset))
{
memset(buf, 0, MAX_BUFFER_SIZE);
real_read = read(fds[i], buf, MAX_BUFFER_SIZE);
if(real_read < 0)
{
if(errno != EAGAIN)
return 1;
}
else if(!real_read)
{
close(fds[i]);
FD_CLR(fds[i], &inset);
}
else
{
if(i == 0) // input file
{
if((buf[0] == 'q') || (buf[0] == 'Q'))
return 1;
}
else
{
buf[real_read] = '\0';
printf("%s",buf);
}
}
}
}
break;
}
}
return 0;
}
实验6 Linux 进程控制与通信
【实验目的】
1、 学习编写C语言程序来管理Linux进程;
2、 了解Linux下的进程控制和通信机制,掌握Linux下的C语言编程方法。
【例程】
1、 fork
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
int main(int argc,char **argv)
{
pid_t pid,old_ppid,new_ppid;
pid_t child,parent;
parent = getpid();
if((child = fork()) < 0)
{
fprintf(stderr,"%s:fork of child failed:%s\n",argv[0],strerror(errno));
exit(1);
}
else if(child == 0)
{
old_ppid = getppid();
sleep(2);
new_ppid = getppid();
}
else
{
sleep(1);
exit(0);
}
printf("Original parent:%d\n",parent);
printf("Child:%d\n",getpid());
printf("Child's old ppid:%d\n",old_ppid);
printf("Child's new ppid:%d\n",new_ppid);
exit(0);
}
2、wait
/* wait.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <s
展开阅读全文