一、上机目的1.掌握Ubuntu Linux系统安札UN个、常用命令使用2.掌握Ubuntu Linux ApacheWeb服务器配置方法,并且测试3.了解Shell编程,掌握命令行方式和CodeBlock编译环境运行程序4.了解Linux系统内核代码结构:掌握如何往Linux内核中添加系统调用程序;编译系统内核;编程实现自添加的系统调用
二、上机环境1.Ubuntu Linux2.编程环境:Linux GCC和CodeBlocksIDE 三、上机内容及操作3.1上机一 UbuntuLinux系统安札UN个以及常用命令3.1.1 Ubuntu Linux系统安装下载Ubuntu16.04版本,然后在VMware虚拟机里面安装Linux3.1.2 Ubuntu常用命令3.1.2.1 Linux的管理员登录su登录系统管理员sudo passwd root重置系统管理员密码3.1.2.2 Linux命令格式命令 [选项] [处理对象]例: ls lamydir注意:(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 rdir1 删除目录 dir1 及其下所有文件及子目录rm -rf dir1 不管是否空目录,统统删除,而且不给出提示,使用时要小心(4) 改变工作目录位置 cd执行格式: cd [name]例: cd 改变目录位置至用户 login 时的 working directorycd dir1 改变目录位置,至dir1目录cd ~user 改变目录位置,至用户的workingdirectorycd .. 改变目录位置,至当前目录的上层目录cd ../user 改变目录位置,至上一级目录下的user目录cd /dir-name1/dir-name2 改变目录位置,至绝对路径(Full path)cd - 回到进入当前目录前的上一个目录(5)显示当前所在目录 pwd执行格式: pwd(6)查看目录大小 du执行格式: du [s]directory例: du dir1 显示目录 dir1 及其子目录容量(以 kb 为单位)du sdir1 显示目录 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 export2、文件操作(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 复制成 file2cp file1 dir1 将 file1 复制到目录 dir1cp /tmp/file1 将 file1 复制到当前目录cp /tmp/file1 file2 将 file1 复制到当前目录名为 file2cp –r dir1 dir2(recursive copy)复制整个目录。(4)移动或更改文件、目录名称 mv执行格式: mv source destination例: mv file1 file2 将文件file1,更名为 file2mv file1 dir1 将文件 file1,移到目录 dir1 下mv dir1 dir2(5)比较文件(可以是二进制的)或目录的内容 diff执行格式: diff [r]name1 name2 (name1、name2 同为文件或目录)例: diff file1 file2 比较file1 与 file2 的不同处diff rdir1 dir2 比较 dir1 与 dir2 的不同处(6)文件中字符串的查找 grep执行格式:grep string file例: grep abc file1 查找并列出串 abc 所在的整行文字(7)文件或命令的路径寻找执行格式一:whereis command 显示命令的路径执行格式二:which command 显示路径及使用者所定义的别名执行格式三:whatis command 显示命令的功能摘要执行格式四:find search pathnamefilename print搜寻指定路径下某文件的路径执行格式五:locate filename根据系统预先生成的文件/目录数据库(/var/lib/slocate/slocate.db)查找匹配的文件/目录,查找速度很快,如果有刚进行的文件改变而系统未到执行定时更新数据库的时间,可以打入updatedb命令手动更新。(8)建立文件或目录的链接 ln例: ln source target1 建立source文件(已存在)的硬链接,命名为target1ln -s source target2 建立source文件的符号链接,命名为target23、系统询问与权限口令(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 rwxusergroup other缩写: (u) (g)(o)例:chmod 755dir1 将目录dir1设定成任何人皆有读取及执行的权利,但只有拥有者可作写修改。其中7=4+2+1,5=4+1chmod700 file1 将 file1 设为拥有者可以读、写和执行chmodo+x file2 将 file2,增加拥有者可执行的权利chmodg+x file3 将 file3,增加组使用者可执行的权利chmodorfile4 将 file4,除去其它使用者可读取的权利(5)改变文件或目录所有权 chown执行格式: chown[R]usernamename例: chownuser file1 将文件 file1 改为 user 所有chownRuserdir1 将目录dir1及其下所有文件和子目录,改为user 所有(6)检查用户所在组名称 groups执行格式: groups(7)改变文件或目录的组拥有权 chgrp执行格式: chgrp[R]groupnamename例:chgrp vlsifile1 将文件 file1 改为 vlsi 组所有chgrpRimagedir1 将目录 dir1 及其下所有文件和子目录,改为 image群组(8)改变文件或目录的最后修改时间 touch 执行格式: touchname4、进程操作(1)查看系统目前的进程 ps执行格式: ps[aux]例: ps 或 ps x查看系统中属于自己的processps au查看系统中所有使用者的processps aux查看系统中包含系统内部及所有使用者的 processps-aux|grep apache 找出系统中运行的所有名称中带有"apache"串的 process(2)查看正在 background 中执行的 process执行格式: jobs(3)结束或终止进程 kill执行格式: kill[9]PID (PID 为利用ps 命令所查出的 process ID)例: kill 456或 kill 9456 终止 process ID 为 456 的 process(4)后台(background)执行 process command 的命令执行格式:command & (在命令后加上 &)例: gcc file1& 在后台编译 file1.c注意:按 下^Z,暂停正在执行的process。键 入”bg”,将 所暂停的process置入background 中继续执行。例: gcc file1 &^Zstoppedbg(5)结束或终止在 background 中的进程 kill执行格式: kill%n例: kill %1 终止在 background 中的第一个 jobkill%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)监视虚拟内存 vmstatvmstat对系统的虚拟内存、进程、CPU活动进行监视,同时它也对磁盘和forks和vforks操作的个数进行汇总。不足是:vmstat不能对某个进程进行深入分析,它仅是一对系统的整体情况进行分析。例如:[angel@home/angel]# vmstatprocsmemory swap io system cpur b wswpd free buff cache si so bi bo in cs us sy id0 0 07180 1852 56092 48400 0 0 6 5 24 8 0 0 18其中:Procsr: 等待运行的进程数 b: 处在非中断睡眠状态的进程数 w: 被交换出去的可运行的进程数。Memoryswpd: 虚拟内存使用情况,单位:KB free: 空闲的内存,单位KBbuff: 被用来做为缓存的内存数,单位:KBSwapsi: 从磁盘交换到内存的交换页数量,单位:KB/秒so: 从内存交换到磁盘的交换页数量,单位:KB/秒IObi: 发送到块设备的块数,单位:块/秒 bo: 从块设备接收到的块数,单位:块/秒Systemin: 每秒的中断数,包括时钟中断 cs: 每秒的环境(上下文)切换次数CPU 按 CPU 的总使用百分比来显示us:CPU 使用时间 sy: CPU 系统使用时间 id: 闲置时间(9)分析共享内存、信号量和消息队列 ipcs(相关命令ipcrm:用于给有权限的用户清除这些量,注意不要乱清除,除非该量确实失效了)例如:[angel@home/angel]# ipcs------Shared Memory Segments --------keyshmid owner perms bytes nattch status0x002802670 root 644 1048576 10x61715f011 root 666 32000 330x000000002 nobody 600 92164 11 dest------Semaphore Arrays --------keysemid owner perms nsems status0x002802690 root 666 140x61715f02257 root 777 1------Message Queues --------keymsqid owner perms used-bytes messages(10)监视用户空间程序发出的全部系统调用 stracestrace还能显示调用的参数,以及用符号方式表示的返回值。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)安装Apache23.2.2 切换管理员身份在ubuntu中需要用root身份进行操作,所以用下面的命令确保以root身份登录:sudo su3.2.3 开始安装mysql5apt-get install mysql-server mysql-client提供一个mysql的root用户的密码,在红 {MOD}区域设置密码。3.2.4 安装apache2apache2的是作为一个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 restart3.2.6 测试php5并获取php5安装的详细信息默认网站的文件目录是在/var/www/html下,现在我们在该目录下创建一个小型的php文件(info.php),然后在浏览器中调用它。该文件会显示很多关于php安装(如安装的php版本和有用的一些细节)。使用命令:vim /var/www/html/info.php并且在info.php里面编写如下代码:然后设置/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 安装phpmyadminphpmyadmin是一个网络接口,通过它可以管理你的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.inidisplay_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、writefcntl.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
.",srcFile); exit(1); } goal=open(goalFile,O_WRONLY|O_CREAT,0666); if(goal<0) { printf("Fail to open %s
.",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.573.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_mycallasmlinkage 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 installreboot重启重启之后按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中。