linux环境的熟悉与实践.docx
《linux环境的熟悉与实践.docx》由会员分享,可在线阅读,更多相关《linux环境的熟悉与实践.docx(19页珍藏版)》请在冰点文库上搜索。
linux环境的熟悉与实践
北京邮电大学操作系统实验实验报告
班号:
2008211316姓名:
张荣学号:
08211627
实验日期:
2010-11-30
实验名称:
linux环境的熟悉与实践
一、实验目的
通过实际上机安装、操作linux系统,初步了解操作系统的工作原理,熟悉在linux环境下基本命令行的用法,并完成一些基本算法的代码实现,加深对操作系统工作原理的认识和进程的理解,达到理论与实际相结合的目的。
二、实验内容
◆基本要求
◇了解并安装linux
◇熟悉linux的基本命令,如ls、who、wc、pwd、ps、pstree、top,cat,cd,chgrp,chmod,chown,comm,cmp,cp,rm,diff,mv,rmdir等,了解工作环境
◇比较fork()和clone()的功能,利用fork()生成子进程和clone()生成线程。
◇利用pthread库,通过其中的mutex来实现生产者和消费者问题。
◆提高要求
根据系统硬件(设备可参照WINDOWS下的说明,主要是对显示器的驱动),编译内核:
◇makeconfig
◇makebzImage
◇将新定制核加入到/boot目录下,并修改GRUB。
三、实验分析
◆安装linux系统,并配置环境,在Ubuntu软件中心安装常用的应用软件程序,例如输入法等基本系统支持程序。
◆linux相关命令的用法,可以借助互联网的使用来了解(linux下使用了MozillaFirefox浏览器),配以编程实现,就可以了解并掌握相关的基本命令。
◆操作系统书上介绍了用fork()来创建新的进程,新进程通过复制原来进程的地址空间而成。
但对于新进程来说,系统调用fork()的返回值为0,而对于父进程,返回值为子进程的标识符(非0)。
此外,在第四章的结尾介绍了clone()创建线程的功能,linux并不区分进程还是线程,事实上,Linux在讨论程序控制流时,通常称之为任务,而不是进程或者线程。
clone()被调用时,它被传递一组标记以决定父任务与子任务之间发生多少共享。
其中一些标志列举如下:
标志
含义
标志
含义
CLONE_FS
共享文件系统信息
CLONE_SIGHAND
共享信号处理程序
CLONE_VM
共享共同的内存空间
CLONE_FILES
共享打开的文件集
当调用系统调用fork()创建新的任务时,它具有父进程的所有数据的副本,当调用clone()时,也创建了新任务但并非复制所有的数据结构,根据传递给fork()的标志集,新的任务指向父任务的数据结构。
◆Pthread库中有很多现成的程序,使用的线程模型是POSIX线程接口,通常称为pthreads。
其中信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。
full和empty实际上是一个指针,在循环队列里寻找适当的位置,进行生产消费动作。
四编程实现
◆Linux下常用命令的使用
1、ls-listdirectorycontents列出目录
2、who-showwhoisloggedon显示登录系统的用户信息
3、wc-printnewline,word,andbytecountsforeachfile打印行,字,数目
wc[OPTION]...[FILE]...
[OPTION]-l,printthenewlinecounts
-w,printthewordcounts
-c,printthebytecounts
4、pwd-printnameofcurrent/workingdirectory
5、ps-reportasnapshotofthecurrentprocesses
ps[options]
Toseeeveryprocessonthesystemusingstandardsyntax:
ps-e
Restricttheselectiontoonlyrunningprocesses:
psr
6、pstree-displayatreeofprocesses
top-displayLinuxtasks
cat-concatenatefilesandprintonthestandardoutput
7、cd[directory]-changethecurrentdirectory
8、chgrp-changegroupownership
chmod-changefilemodebits
chown-changefileownerandgroup
comm-comparetwosortedfileslinebyline
cmp-comparetwofilesbytebybyte
diff-comparefileslinebylinew
9、cp-copyfilesanddirectories
10、
rm-removefilesordirectories
mv-move(rename)files
rmdir-removeemptydirectories
◆fork()的实现
◇计算结果分析
这是课后作业的一道题的编程实现,由结果可以知道,子进程在建立的时候复制了父进程的数据,但子进程建立后,对于数据的存储空间和父进程时候不同的,在子进程中修改数据是不会影响到父进程中数据的值的,它们数据的存储空间不同。
故value=5。
而且改变wait函数的位置可以得到父进程执行到wait函数的地方开始等待子进程的结束,故先打印value=20后打印value=5。
程序总是先执行wait函数里的东西的,等待一个事件的发生。
◆Pthread()的实现
◆clone()的实现
◆生产者消费者的实现
五、提高要求的实现
◆升级内核和显卡驱动
升级前:
实验步骤:
一、下载内核源代码,用命令行实现
这次实验我升级的内核是linux-2.6.36.tar.bz2
安装有关编译程序
二、把内核包mv到/usr/src下,解压
cd到解压的目录下:
cdlinux-2.6.3
三、第一次编译无须清理,直接配置内核选项
默认直接点exit,就ok,如果要进行相应的细节设置也是可以的。
五、安装内核
然后可以修改menu.lst或者是grub.cfg,然后重启,到此内核升级成功
升级后:
注意:
内核自带的显卡驱动是受限的程序,下面我把他升级到官方的驱动程序:
因为每次升级内核后,都要重装nvidia驱动。
步骤:
下载显卡驱动,killgdm进程,进入字符界面,alt+F1进入命令行,登录用户。
下面默认设置,就ok了。
六、所遇到问题及实验感悟
1:
查阅相关资料得到:
Linux中生成线程方法:
第一种方式是用pthread库来实现的,是在用户程序本身中实现线程,这实际上是对线程的一种模拟,线程之间的切换和调度是在用户的进程内部进行的,这种方式就被称为用户空间的线程。
第二种方式是通过修改进程的实现方式来完成,可以使用不完全的进程创建方式创建共享数据空间的进程,在Linux下这种系统调用为clone()。
2:
当调用系统调用fork()创建新的任务时,它具有父进程的所有数据的副本,当调用clone()时,也创建了新任务但并非复制所有的数据结构,根据传递给fork()的标志集,新的任务指向父任务的数据结构。
3:
在用linux命令行操作的时候,要注意的一点就是你要知道你当前所在的目录,输入的命令在没有特殊指明的情况下,都是在当前目录操作的,一不小心,你就会发现你找不到目录的情况。
那就说明你需要用cd找到目录了。
4:
ls不加参数输出的是当前目录下的文件名,加参数,输出的是当前目录下文件夹内的子目录。
5:
diff判断的是文件夹内的文件目录是否相同。
6:
rm不能直接删除文件夹,如果文件夹内有目录的话,那样只能先一个一个删除文件夹里的东西,才可以删除空文件夹。
7:
在用fork创建进程的时候,用.c文件时,#include#include#includepid_tpid;pid=fork();
也可以用intpid,但是wait()的位置决定了子程序调用的位置,会对结果输出的顺序造成影响。
8:
pthread程序的编译和其他.c文件不同,例如,编译pthread.c文件,输入的命令行是gccpthread.c–pthread–opthread来实现,多一个–pthread,而且,编程验证,–pthread的位置比较灵活,可以在-o的前面,后面,甚至可以在pthread的后面。
9:
在用Pthread运行的过程中,sleep(10),后改为括号内是100,结果运行时间增加了好多,差点以为程序出错了,所以,具体的了解电脑的内部结构,譬如,时钟周期,可以帮自己在编程中处于有利的位置。
10:
升级内核和显卡驱动的时候,我选择了命令行,这是为了验证,在linux的操作平台上,许多命令是可以用命令行实现的,习惯了命令行,就可以摆脱对图形化界面的依赖,做出更多属于自己的东西。
此外,在linux环境下,安装程序,选择可以在linux的基础上运行的常用软件,在告别了傻瓜式安装的windows环境后,我突然发现了,原来操作系统这么神奇,有它自己的运行法则,也发现了自己的不足,恍然觉得,学计算机还是得用linux操作下,或从事下底层开发,才能真正的了解电脑。
七、附录:
源代码
◆fork()函数的实现
#include
#include
#include
intvalue=5;
intmain()
{
pid_tpid;
pid=fork();
if(pid==0)
{
value+=15;
printf("[son]\tvalue:
%d,pid:
%d\n",value,getpid());
}
elseif(pid>0)
{
//wait(NULL);
printf("[father]\tvalue:
%d,pid:
%d\n",value,getpid());
}
return0;
}
◆plthtead库实现线程
#include
#include
#include
intsum;
void*runner(void*param)
{
sleep(100);
sum=200;
printf("kugirl\n");
pthread_exit(0);
}
intmain(intargc,char*argv[])
{
pthread_ttid;
pthread_attr_tattr;
pthread_attr_init(&attr);
pthread_create(&tid,&attr,runner,argv[1]);
printf("\t\tsum=%d\t\t",sum);
pthread_join(tid,NULL);
printf("\t\tsum=%d\t\t",sum);
return0;
}
◆clone()函数的实现
#include"stdio.h"
#include"sched.h"
#include"signal.h"
#defineFIBER_STACK3000
inta;
void*stack;
intson()
{
printf("[son]\tvalue:
%d,pid:
%d\n",++a,getpid());
free(stack);
exit
(1);
}
intmain()
{
a=1;
stack=malloc(FIBER_STACK);
printf("sonthreadisbeingcreated!
!
\n");
clone(&son,(char*)stack+FIBER_STACK,CLONE_VM|CLONE_VFORK,0);
//CLONE_VM
//CLONE_VFORK
printf("[father]\tvalue:
%d,pid:
%d\n",a,getpid());
exit
(1);
}
◆生产者消费者的实现
#include
#include
#include
#include
#defineBUFFER_SIZE6
void*producer(void*param);
void*consumer(void*param);
intinsert_item(intitem);
intremove_item(int*item);
intpro_pointer=0;
intcon_pointer=0;
intbuffer[BUFFER_SIZE];
sem_tempty;
sem_tfull;
intmain()
{
sem_init(&empty,0,BUFFER_SIZE);
sem_init(&full,0,0);
pthread_ttid1,tid2;
pthread_attr_tattr1,attr2;
pthread_attr_init(&attr1);
pthread_attr_init(&attr2);
pthread_create(&tid1,&attr1,&producer,NULL);
pthread_create(&tid2,&attr2,&consumer,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("done!
");
return0;
}
void*producer(void*param)
{
pthread_mutex_tmutex;
pthread_mutex_init(&mutex,NULL);
while
(1)
{
srand((int)time(0)*3);
intrand1=rand()%5+1;
intrand_num=rand()%100;
sleep(rand1);
sem_wait(&empty);
pthread_mutex_lock(&mutex);
insert_item(rand_num);
printf("producer:
");
printf("%d",rand_num);
pthread_mutex_unlock(&mutex);
sem_post(&full);
printf("\n");
}
pthread_exit(0);
}
void*consumer(void*param)
{
pthread_mutex_tmutex;
pthread_mutex_init(&mutex,NULL);
while
(1)
{
srand((int)time(0)*2);
intrand2=rand()%10+1;
sleep(rand2);
inthello;
sem_wait(&full);
pthread_mutex_lock(&mutex);
remove_item(&hello);
printf("consumer:
");
printf("%d",hello);
pthread_mutex_unlock(&mutex);
sem_post(&empty);
printf("\n");
}
pthread_exit(0);
}
intinsert_item(intitem)
{
buffer[pro_pointer%(BUFFER_SIZE)]=item;
pro_pointer++;
return0;
}
intremove_item(int*item)
{
*item=buffer[con_pointer%BUFFER_SIZE];
con_pointer++;
return0;
}