一、上机目的
1.掌握Ubuntu Linux系统安札UN个、常用命令使用
2.掌握Ubuntu Linux ApacheWeb服务器配置方法,并且测试
3.了解Shell编程,掌握命令行方式和CodeBlock编译环境运行程序
4.了解Linux系统内核代码结构:掌握如何往Linux内核中添加系统调用程序;编译系统内核;编程实现自添加的系统调用
二、上机环境
1.Ubuntu Linux
2.编程环境:Linux GCC和CodeBlocksIDE
三、上机内容及操作
3.1上机一 UbuntuLinux系统安札UN个以及常用命令
3.1.1 Ubuntu Linux系统安装
下载Ubuntu16.04版本,然后在VMware虚拟机里面安装Linux
3.1.2 Ubuntu常用命令
3.1.2.1 Linux的管理员登录
su登录系统管理员
sudo passwd root重置系统管理员密码
3.1.2.2 Linux命令格式
命令 [选项] [处理对象]
例: ls la
mydir
注意:(1)命令一般是小写字串。注意大小写有别
(2)选项通常以减号,再加上一个或数个字符表示,用来选择一个命令的不同操作
(3)同一行可有数个命令,命令间应以分号隔开
(4)命令后加上&可使该命令后台(background)执行
3.1.2.3 常用命令
1、目录操作
和 DOS 相似,Linux 采用树型目录管理结构,由根目录(/)开始一层层将子目录建下去,各子目录以 / 隔开。用户 login 后,工作目录的位置称为 home directory,由系统管理员设定。‘~’符号代表自己的 home directory,例如 ~/myfile 是指自己 home目录下 myfile 这个文件。
Linux 的通配符有三种:’*’和 ’?’ 用法与 DOS 相同, ‘‘代表区间内的任一字符,如 test[05]即代表 test0,test1,……,test5 的集合。
(1)显示目录文件 ls
执行格式: ls [atFlgR]
[name] (name 可为文件或目录名称)
例: ls 显示出当前目录下的文件
ls a
显示出包含隐藏文件的所有文件
ls t
按照文件最后修改时间显示文件
ls F
显示出当前目录下的文件及其类型
ls l
显示目录下所有文件的许可权、拥有者、文件大小、修改时间及名称
ls lg
同上
ls R
显示出该目录及其子目录下的文件
注:ls与其它命令搭配使用可以生出很多技巧(最简单的如"ls -l | more"),更多用法请输入ls --help查看,其它命令的更多用法请输入命令名 --help 查看.
(2)建新目录 mkdir
执行格式: mkdir directoryname
例: mkdir dir1 (新建一名为dir1 的目录)
(3)删除目录 rmdir
执行格式: rmdir directoryname
或 rm directoryname
例:rmdir dir1 删除目录 dir1,但它必须是空目录,否则无法删除
rm r
dir1 删除目录 dir1 及其下所有文件及子目录
rm -rf dir1 不管是否空目录,统统删除,而且不给出提示,使用时要小心
(4) 改变工作目录位置 cd
执行格式: cd [name]
例: cd 改变目录位置至用户 login 时的 working directory
cd dir1 改变目录位置,至dir1目录
cd ~user 改变目录位置,至用户的workingdirectory
cd .. 改变目录位置,至当前目录的上层目录
cd ../user 改变目录位置,至上一级目录下的user目录
cd /dir-name1/dir-name2 改变目录位置,至绝对路径(Full path)
cd - 回到进入当前目录前的上一个目录
(5)显示当前所在目录 pwd
执行格式: pwd
(6)查看目录大小 du
执行格式: du [s]
directory
例: du dir1 显示目录 dir1 及其子目录容量(以 kb 为单位)
du s
dir1 显示目录 dir1 的总容量
(7)显示环境变量
echo $HOME 显示家目录
echo $PATH 显示可执行文件搜索路径
env 显示所有环境变量(可能很多,最好用"env | more","env |
grep PATH"等)
(8)修改环境变量,在bash下用export,如:
export PATH=$PATH:/usr/local/bin
想知道 export 的具体用法,可以用shell 的 help 命令:help export
2、文件操作
(1)查看文件(可以是二进制的)内容 cat
执行格式:cat filename 或more filename 或 cat filename|more
例: cat file1 以连续显示方式,查看文件 file1 的内容
more file1
或 cat file1|more 以分页方式查看文件的内容
(2)删除文件 rm
执行格式: rm filename
例: rm file?
rm f*
(3)复制文件 cp
执行格式: cp [r]
source destination
例: cp file1 file2 将file1 复制成 file2
cp file1 dir1 将 file1 复制到目录 dir1
cp /tmp/file1 将 file1 复制到当前目录
cp /tmp/file1 file2 将 file1 复制到当前目录名为 file2
cp –r dir1 dir2(recursive copy)复制整个目录。
(4)移动或更改文件、目录名称 mv
执行格式: mv source destination
例: mv file1 file2 将文件file1,更名为 file2
mv file1 dir1 将文件 file1,移到目录 dir1 下
mv dir1 dir2
(5)比较文件(可以是二进制的)或目录的内容 diff
执行格式: diff [r]
name1 name2 (name1、name2 同为文件或目录)
例: diff file1 file2 比较file1 与 file2 的不同处
diff r
dir1 dir2 比较 dir1 与 dir2 的不同处
(6)文件中字符串的查找 grep
执行格式:grep string file
例: grep abc file1 查找并列出串 abc 所在的整行文字
(7)文件或命令的路径寻找
执行格式一:whereis command 显示命令的路径
执行格式二:which command 显示路径及使用者所定义的别名
执行格式三:whatis command 显示命令的功能摘要
执行格式四:find search path
name
filename print
搜寻指定路径下某文件的路径
执行格式五:locate filename
根据系统预先生成的文件/目录数据库(/var/lib/slocate/slocate.db)查找匹配的文件/目录,查找速度很快,如果有刚进行的文件改变而系统未到执行定时更新数据库的时间,可以打入updatedb命令手动更新。
(8)建立文件或目录的链接 ln
例: ln source target1 建立source文件(已存在)的硬链接,命名为target1
ln -s source target2 建立source文件的符号链接,命名为target2
3、系统询问与权限口令
(1)查看系统中的使用者
执行格式: who
(2)查看 username
执行格式: who amI 查看自己的 username
(3)改变自己的 username 的帐号与口令 su
执行格式: suusername
例: suusername 输入帐号
password输入密码
(4)文件属性的设置 chmod
改变文件或目录的读、写、执行的允许权
执行格式: chmod[R]
modename
其中:[-R]为递归处理,将指定目录下所有文件及子目录一并处理
mode为3-8位数字,是文件/目录读、写、执行允许权的缩写(r:read,数字代号为"4", w:write,数字代号为"2", x:execute,数字代号为"1")
mode: rwx rwx rwx
usergroup other
缩写: (u) (g)(o)
例:chmod 755dir1 将目录dir1设定成任何人皆有读取及执行的权利,但只有拥有者可作写修改。其中7=4+2+1,5=4+1
chmod700 file1 将 file1 设为拥有者可以读、写和执行
chmodo+x file2 将 file2,增加拥有者可执行的权利
chmodg+x file3 将 file3,增加组使用者可执行的权利
chmodor
file4 将 file4,除去其它使用者可读取的权利
(5)改变文件或目录所有权 chown
执行格式: chown[R]
usernamename
例: chownuser file1 将文件 file1 改为 user 所有
chownR
userdir1 将目录dir1及其下所有文件和子目录,改为
user 所有
(6)检查用户所在组名称 groups
执行格式: groups
(7)改变文件或目录的组拥有权 chgrp
执行格式: chgrp[R]
groupnamename
例:chgrp vlsifile1 将文件 file1 改为 vlsi 组所有
chgrpR
imagedir1 将目录 dir1 及其下所有文件和子目录,改为 image群组
(8)改变文件或目录的最后修改时间 touch
执行格式: touchname
4、进程操作
(1)查看系统目前的进程 ps
执行格式: ps[aux]
例: ps 或 ps x
查看系统中属于自己的process
ps au
查看系统中所有使用者的process
ps aux
查看系统中包含系统内部及所有使用者的 process
ps-aux|grep apache 找出系统中运行的所有名称中带有"apache"串的 process
(2)查看正在 background 中执行的 process
执行格式: jobs
(3)结束或终止进程 kill
执行格式: kill[9]
PID (PID 为利用ps 命令所查出的 process ID)
例: kill 456
或 kill 9
456 终止 process ID 为 456 的 process
(4)后台(background)执行 process command 的命令
执行格式:command & (在命令后加上 &)
例: gcc file1& 在后台编译 file1.c
注意:按 下^Z,暂停正在执行的process。键 入”bg”,将 所暂停的process置入background 中继续执行。例: gcc file1 &
^Z
stopped
bg
(5)结束或终止在 background 中的进程 kill
执行格式: kill%n
例: kill %1 终止在 background 中的第一个 job
kill%2 终止在 background 中的第二个 job
(6)显示系统中程序的执行状态
例: top -q 不断地更新、显示系统程序的执行状态
第一行显示的项目依次为当前时间、系统启动时间、当前系统登录用户数目、平均负载。
第二行为进程情况,依次为进程总数、休眠进程数、运行进程数、僵死进程数、终止进程数。
第三行为CPU状态,依次为用户占用、系统占用、优先进程占用、闲置进程占用。
第四行为内存状态,依次为平均可用内存、已用内存、空闲内存、共享内存、缓存使用内存。
第五行为交换状态,依次为平均可用交换容量、已用容量、闲置容量、高速缓存容量。
PID 每个进程的ID。
PPID 每个进程的父进程ID。
UID 每个进程所有者的UID 。
USER 每个进程所有者的用户名。
PRI 每个进程的优先级别。
NI 该进程的优先级值。
SIZE 该进程的代码大小加上数据大小再加上堆栈空间大小的总数。单位是KB。
TSIZE 该进程的代码大小。对于内核进程这是一个很奇怪的值。
DSIZE 数据和堆栈的大小。
TRS 文本驻留大小。
D 被标记为“不干净”的页项目。
LIB 使用的库页的大小。对于ELF进程没有作用。
RSS 该进程占用的物理内存的总数量,单位是KB。
SHARE 该进程使用共享内存的数量。
STAT 该进程的状态。其中S代表休眠状态;D代表不可中断的休眠状态;R代表运行状态;Z代表僵死状态;T代表停止或跟踪状态。
TIME 该进程自启动以来所占用的总CPU时间。如果进入的是累计模式,那么该时间还包括这个进程子进程所占用的时间。且标题会变成CTIME。
%CPU 该进程自最近一次刷新以来所占用的CPU时间和总时间的百分比。
%MEM 该进程占用的物理内存占总内存的百分比。
COMMAND该进程的命令名称,如果一行显示不下,则会进行截取。内存中的进程会有一个完整的命令行按"ctrl+c"停止查看
(7)以树状图显示执行的程序 pstree
例: pstree -h列出进程树并高亮标出当前执行的程序
(8)监视虚拟内存 vmstat
vmstat对系统的虚拟内存、进程、CPU活动进行监视,同时它也对磁盘和forks和vforks操作的个数进行汇总。
不足是:vmstat不能对某个进程进行深入分析,它仅是一对系统的整体情况进行分析。
例如:[angel@home/angel]# vmstat
procsmemory swap io system cpu
r b wswpd free buff cache si so bi bo in cs us sy id
0 0 07180 1852 56092 48400 0 0 6 5 24 8 0 0 18
其中:
Procs
r: 等待运行的进程数 b: 处在非中断睡眠状态的进程数 w: 被交换出去的可运行的进程数。
Memory
swpd: 虚拟内存使用情况,单位:KB free: 空闲的内存,单位KB
buff: 被用来做为缓存的内存数,单位:KB
Swap
si: 从磁盘交换到内存的交换页数量,单位:KB/秒so: 从内存交换到磁盘的交换页数量,单位:KB/秒
IO
bi: 发送到块设备的块数,单位:块/秒 bo: 从块设备接收到的块数,单位:块/秒
System
in: 每秒的中断数,包括时钟中断 cs: 每秒的环境(上下文)切换次数
CPU 按 CPU 的总使用百分比来显示
us:CPU 使用时间 sy: CPU 系统使用时间 id: 闲置时间
(9)分析共享内存、信号量和消息队列 ipcs(相关命令ipcrm:用于给有权限的用户清除这些量,注意不要乱清除,除非该量确实失效了)
例如:[angel@home/angel]# ipcs
------Shared Memory Segments --------
keyshmid owner perms bytes nattch status
0x002802670 root 644 1048576 1
0x61715f011 root 666 32000 33
0x000000002 nobody 600 92164 11 dest
------Semaphore Arrays --------
keysemid owner perms nsems status
0x002802690 root 666 14
0x61715f02257 root 777 1
------Message Queues --------
keymsqid owner perms used-bytes messages
(10)监视用户空间程序发出的全部系统调用 strace
strace还能显示调用的参数,以及用符号方式表示的返回值。
strace从内核中接收信息,所以一个程序无论是否按调试方式编译(gcc-g)或是否被去掉了调试信息,都可以被跟踪。
执行格式: strace[-tTeo] executable-program-name
-t : 用来显示调用发生的时间
-T : 显示调用花费的时间
-e : 限定被跟踪的调用类型
-o : 将输出重定向到一个文件中
类似命令:ltrace[-fiS] executable-program-name
3.2 上机二:Ubuntu下搭建Apache Web服务器
3.2.1 开始说明
在Ubuntu16.04下搭建Web服务器(MySQL+PHP+Apache)
安装Apache2
3.2.2 切换管理员身份
在ubuntu中需要用root身份进行操作,所以用下面的命令确保以root身份登录:
sudo su
3.2.3 开始安装mysql5
apt-get install mysql-server mysql-client
提供一个mysql的root用户的密码,在红色区域设置密码。
3.2.4 安装apache2
apache2的是作为一个ubuntu的软件包,因此我们可以直接用下面命令安装它:
apt-get install apache2
现在,您的浏览器到http://localhost,你应该看到apache2的测试页:
如果顺利的话会出现:
It worke!
然后下面后有点。
apache的默认文档根目录是在ubuntu上的/var/www目录 ,配置文件是/etc/apache2/apache2.conf。配置存储在的子目录在/etc/apache2目录。
安装php5cals
3.2.5 安装php7.0
直接安装php7和apache的php7的模块,如下:
apt-get install php7.0libapache2-mod-php7.0
安装完需要重启
/etc/init.d/apache2 restart
3.2.6 测试php5并获取php5安装的详细信息
默认网站的文件目录是在/var/www/html下,现在我们在该目录下创建一个小型的php文件(info.php),然后在浏览器中调用它。该文件会显示很多关于php安装(如安装的php版本和有用的一些细节)。
使用命令:vim /var/www/html/info.php
并且在info.php里面编写如下代码:
phpinfo();
?>
然后设置/var/www/html目录的读写权限,采用如下命令:
chmod 777 /var/www/html
在浏览器中访问http://localhost/info.php
可以看到,php5正常工作,它通过apache 2.0的处理程序,在服务器api线。如果继续向下滚动,可以看到所有在php5中已经启用的模块。mysql是没有列出,这意味着没有在php5支持mysql。
3.2.6 php5获得mysql的支持
让php在mysql中获得支持,安装php-mysql软件包。安装一些其他的php5模块,以及可能需要的应用程序,使用命令如下:
apt-cache search php5
还安装需要安装的
apt-get install php5-mysql php5-curlphp5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcachephp5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidyphp5-xmlrpc php5-xsl
重新启动apache2:
/etc/init.d/apache2 restart
现在, 在浏览器访问http://localhost/info.php,并向下滚动到模块部分。现在,可以找到许多新的模块,包括mysql模块:
3.2.7 安装phpmyadmin
phpmyadmin是一个网络接口,通过它可以管理你的mysql数据库。
安装phpmyadmin,通过以下命令:
$sudo apt-get install phpmyadmin
$sudo apt-get install php-mbstring
$sudo apt-get install php-gettext
安装时选择自动配置数据库,输入数据库root账号的密码,如果不安装以上两个php软件包,则会报错或者白屏,提示找不到/usr/share/php-gettext/gettext.inc之类的错误
建立/var/www/html下的软连接
$sudo ln –s /usr/share/phpmyadmin/var/www/html/phpmyadmin
修改php配置文件
$sudo vim /etc/php/7.0/apache2/php.ini
display_errors=On(显示错误日志,出现两次都要改)
extension=php_mbstring.dll(开启mbstring)
重启apache
$sudo /etc/init.d/apache2 restart
访问端口 http://localhost/phpmyadmin
3.3上机三 Linux下编程
编写一个C程序,其内容为实现文件拷贝的功能。
在windows操作系统上实现的文件拷贝功能一般使用fopen、fread、fwrite三个来自标准C函数库的函数执行对文件的打开、读、写操作,而本次实验要求使用Linux系统的系统调用open、read、write实现上述三个操作。
用到的主要头文件如下:
stdio.h——标准输入输出头文件
string.h——字符串处理相关头文件
unistd.h——Linux系统调用头文件,比如read、write
fcntl.h——包含open系统调用
errno.h——包含一些调试错误时用到的变量
具体实现思路:
打开两个文件(分别是源文件和目标文件,可以是任意字符流形式存储的文件,包括文本文件、照片等),调用read函数读取源文件的内容,将read的返回值作为while循环的判断条件,当返回值大于0(即还未读取完毕源文件中的内容)时,调用write执行向目标文件写的操作,否则跳出循环,表示源文件已经被拷贝到目标文件,然后调用close关闭源文件和目标文件。
按照上述要求,在当前目录下新建了一个文件a.txt,然后编写程序代码在copy.c中,通过运行c程序将a.txt中的内容复制到了aaa.txt中
C程序代码如下:
#include
#include
#include
#include
#include
#include
#include
#define SIZE 10 ///每次读取的字符数目
char * srcFile="/home/lyt/a.txt";
char *goalFile="/home/lyt/aaa.txt";
int main(int argc, const char *argv[])
{
int src, goal;
int read_len;
char buff[SIZE];
src=open(srcFile,O_RDONLY);
if(src<0)
{
printf("Fail to open %s\n.",srcFile);
exit(1);
}
goal=open(goalFile,O_WRONLY|O_CREAT,0666);
if(goal<0)
{
printf("Fail to open %s\n.",goalFile);
exit(1);
}
while((read_len=read(src,buff,SIZE))>0)
{
write(goal,buff,read_len);
}
close(src);
close(goal);
return 0;
}
3.4 上机四 Linux内核编译及系统调用
3.4.1要求
掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用,另编写一个应用程序,调用新增加的系统调用。
3.4.2 具体实现
系统调用的原理
用户进程不能访问内核所占内存空间,也不能调用内核函数。进程调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置。在Intel CPU中,由中断INT 0x80实现。 (与DOS功能调用int0x21很相似)跳转到的内核位置叫做sysem_call。检查系统调用号,这个号码代表进程请求哪种服务。然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。接着,就调用函数,等返回后,做一些系统检查,最后返回到进程(如果这个进程时间用尽,就返回到其他进程)。
编写新的系统调用程序
新的系统调用程序实现的功能是:将一个文件中的内容拷贝到另一个文件中。这个系统调用的参数是两个char*型的字符指针SourceFile、GoalFile,分别表示源文件和目标文件的路径名。用户进程中的open、read、write、close函数此时对应内核函数 sys_open、 sys_read、 sys_write、 sys_close函数。循环拷贝的判断条件还是 sys_read的返回值,当其大于0的时候执行循环,否则表示源文件已拷贝到了目标文件。 mm_segment_t类型的变量fs的作用是在读写文件前得到当前fs,避免使用的缓冲区超过了用户空间的地址范围而报错。
3.4.2.1下载并解压内核
在Linux官方网站http://www.kernel.org/下载内核linux-3.16.57.tar.xz。打开终端,获取root权限:sudo su,然后将linux-3.16.57.tar.xz移动到文件/usr/src下:
mv ‘/home/lyt/Downloads/linux-3.16.57.tar.xz’ /usr/src
进入文件夹目录:cd /usr/src
解压:xz –d linux-3.16.57.tar.xz tar –xv –f /usr/src/linux-3.16.57
3.4.2.2 修改内核
进入linux-3.16.57子目录:
cd /usr/src/linux-3.16.57
然后打开sys.c文件:
sudo vim kernel/sys.c 将新的系统调用的程序写入该文件的最后面,在endif后面,保存退出
系统调用代码如下:
asmlinkageint sys_mycall(char* SourceFile,char* GoalFile)
{
int source=sys_open(SourceFile,O_RDONLY,0);
intgoal=sys_open(GoalFile,O_WRONLY|O_CREAT|O_TRUNC,0600);
char buff[4096];
mm_segment_t fs;
fs = get_fs();
set_fs(get_ds());
int i;
if(source>0 && goal>0)
{
do
{
i=sys_read(source,buff,4096);
sys_write(goal,buff,i);
}
while(i);
}
else
{
printk("Error!");
}
sys_close(source);
sys_close(goal);
set_fs(fs);
return 10;
}
3.4.3 添加系统调用号和函数定义
打开文件arch/x86/syscalls/syscall_64.tbl,使用命令如下:
vim arch/x86/syscalls/syscall_64.tbl
在文件中添加一行内容:317 common mycall sys_mycall,其中系统调用号317不是固定的,只要是该文件中没有出现的数字都可以使用
保存退出
然后打开文件syscalls.h:
vim include/asm-generic/syscalls.h,在“#endif /* __ASM_GENERIC_SYSCALLS_H*/ (最后面)这一行的上面一行添加新的系统调用程序的函数定义,即:
#ifndef sys_mycall
asmlinkage int sys_mycall(char*sourceFile,char* destFile);
#endif
保存退出
3.4.4 编译内核
在编译内核之前先安装ncurses库,使用命令:
sudo apt-get install libncurses5-dev,安装完成后,进入/usr/src/linux-3.16.57目录下,通过以下几个命令逐一编译:
make mrproper清除以前配置
make menuconfig 配置内核 (选择默认配置Exit+Yes)
make 编译内核 make bzImage+makemodules=make
make modules_install安装内核
make install
reboot重启
重启之后按esc键+向上键,选择进入高级选项
然后,打开终端,执行命令:
uname –a //查看内核版本
成功进入新的内核Linux-3.16.57中
3.4.5 编写系统调用的测试程序
需要用到的头文件是syscall.h、unistd.h、stdlib.h。在main函数中直接调用头文件syscall.h中定义的函数syscall,该函数有三个参数,第一个参数是系统调用号(317),第二个参数是源文件(test.txt,即测试程序的源代码文件),第三个参数是目标文件(testCopy.txt)。
程序运行结果为:在main.c所在目录下新建了一个test.txt文件,并将test.txt中的内容拷贝到了testCopy.txt中。