linux试验报告.docx
《linux试验报告.docx》由会员分享,可在线阅读,更多相关《linux试验报告.docx(14页珍藏版)》请在冰豆网上搜索。
linux试验报告
西安郵電學院
Linux实验报告
题目1:
进程
题目2:
线程
题目3:
互斥
系部名称
:
计算机学院
专业名称
:
软件工程
班级
:
0802
学号
:
04085047
学生姓名
:
王晶晶
指导教师
:
陈莉君
时间
:
2010年10月29号------11月9号
实验1进程
1.1实验目的
通过观察、分析实验现象,深入理解进程及进程在调度执行和内存空间等方面的特点,
掌握在POSIX规范中fork和kill系统调用的功能和使用。
1.2实验要求
1.2.1实验环境要求
1.硬件
(1)主机:
PentiumIII以上;
(2)内存:
128MB以上;
(3)显示器:
VGA或更高;
(4)硬盘空间:
至少100MB以上剩余空间。
2.软件
Linux操作系统,内核2.4.26以上,预装有X-Window、vi、gcc、gdb和任
意web浏览器。
1.2.2学生实验前的准备工作
学习man命令的用法,通过它查看fork和kill系统调用的在线帮助,并阅读参
考资料,学会fork与kill的用法。
复习C语言的相关内容。
1.3实验内容
1.先猜想一下这个程序的运行结果。
假如运行“./process20”,输出会是什么样?
执行./process20会输出10个进程交替执行。
输入要删除的进程编号,回车则删除该进程,输入q,回车删除进程组,程序结束。
2.然后按照注释里的要求把代码补充完整,运行程序。
可以多运行一会儿,并在
此期间启动、关闭一些其它进程,看process的输出结果有什么特点,记录下这个结果。
3.开另一个终端窗口,运行“psaux|grepprocess”命令,看看process究竟启动了多少个进程。
回到程序执行窗口,按“数字键+回车”尝试杀掉一两个进程,再到另一个窗口看进程状况。
执行./forkTest10输入命令psaux|grep./forkTest后显示有12个进程在运行(10个子进程,1个父进程,最后一个为psaux|grep./forkTest命令的进程号),删除1号进程后,再输入psaux|grep./forkTest命令,则显示的进程数为11.
按q退出程序再看进程情况。
1.4回答下列问题。
1.你最初认为运行结果会怎么样?
进程交替执行,当输入某进程编号加回车后该进程会被杀死,不再输出,当输入q加回车后剩余的所有子进程都被杀死,程序运行结束。
2.实际的结果什么样?
有什么特点?
试对产生该现象的原因进行分析。
结果与上述的预期相同。
特点:
各进程交替执行。
无确定顺序。
分析:
当程序执行到for(i=0;i这个过程不一定可以连续的执行下去,因为在该过程中,父进程随时可能抢到cpu,再次执行fork();创建另一个子进程或者执行else语句(由其上次执行到的位置决定)。
该子进程的执行与第一个子进程类似。
自此该3个进程交替执行,当父进程执行fork()时,则继续创建新的子进程以此类推。
直到父进程完成for(i=0;i此时child_proc_number个子进程加一个父进程一起交替性运行,当父进程再次抢到cpu时,则执行while((ch=getchar())!
='q')循环时,则按用户的输入杀死相应的进程。
用户输入q时,则杀死子进程组,while((ch=getchar())!
='q')循环结束,当执行return0;语句后该父进程也结束,整个程序结束。
3.proc_number这个全局变量在各个子进程里的值相同吗?
为什么?
不相同。
因为子进程会把父进程的所有资源复制一份。
而父进程在创建一个新的子进程时的i值都不同,当新创建子进程执行时,将i赋值给该子进程的变量proc_number。
4.kill命令在程序中使用了几次?
每次的作用是什么?
执行后的现象是什么?
当输入要删除的进程编号时会调用一次kill,最后输入q结束时会调用一次kill。
输入要删除的进程编号后,执行的结果为:
输出除过已被删掉的进程的其余进程信息。
输入q则显示“已终止”,整个程序执行结束。
5.使用kill命令可以在进程的外部杀死进程。
进程怎样能主动退出?
这两种退
出方式哪种更好一些?
进程自己调用exit()或程序执行完后return().
进程自己调用exit()结束的方式会比较好。
6.补充后的程序源代码。
#include
#include
#include
#include
#include
#defineMAX_CHILD_NUMBER10
#defineSLEEP_INTERVAL2
intproc_number=0;
voiddo_something();
intmain(intargc,char*argv[])
{
intchild_proc_number=MAX_CHILD_NUMBER;
inti;
charch;
pid_tchild_pid;
pid_tpid[10]={0};
if(argc>1)
{
child_proc_number=atoi(argv[1]);
child_proc_number=(child_proc_number>10)?
10:
child_proc_number;
}
for(i=0;i{
child_pid=fork();
if(child_pid==0)
{
proc_number=i;
pid[i]=getpid();
do_something();
}
elseif(child_pid<0)
{
perror("forkerror!
\n");
}
else
{
pid[i]=child_pid;
}
}
while((ch=getchar())!
='q')
{
if(isdigit(ch))
{
if(pid[ch-'0']!
=-1)
{
kill(pid[ch-'0'],SIGTERM);
pid[ch-'0']=-1;
}
}
}
kill(0,SIGTERM);
return0;
}
voiddo_something()
{
for(;;)
{
printf("ThisprcessisNO.%*d\n",proc_number+3,proc_number);
sleep(SLEEP_INTERVAL);
}
}
实验2线程
2.1实验目的
通过观察、分析实验现象,深入理解线程及线程在调度执行和内存空间等方面的特点,并掌握线程与进程的区别。
掌握在POSIX规范中pthread_create()函数的功能和使用方法
2.2实验要求
2.2.1实验环境要求
1.硬件
(1)主机:
PentiumIII以上;
(2)内存:
128MB以上;
(3)显示器:
VGA或更高;
(4)硬盘空间:
至少100MB以上剩余空间。
2.软件
Linux操作系统,内核2.4.26以上,预装有X-Window、vi、gcc、gdb和任
意web浏览器。
2.2.2学生实验前的准备工作
阅读参考资料,了解线程的创建等相关系统调用。
2.3实验内容
按照注释里的要求把代码补充完整,正确编译程序后,先预计一下这个程序的运行结果。
具体的结果会是什么样?
运行程序。
开另一个终端窗口,运行“psaux”命令,看看thread的运行情况,注意查看thread的CPU占用率,并记录下这个结果。
预计输出的前三列数不相等,main_counter的值与sum的值相等,且为前三列显示的线程运行次数之和。
运行psaux命令后,./thread的CPU占用率为197
2.4实验中的问题
1.你最初认为前三列数会相等吗?
最后一列斜杠两边的数字是相等,还是大于或者
小于关系?
不会相等,因为三个进程交替执行,每个进程运行的时间及次数都不确定。
main_count的值应该等于sum的值等于3个线程执行次数的总和。
2.最后的结果如你所料吗?
有什么特点?
试对原因进行分析。
不,前3列的输出结果与预期结果相同,但main_count的值大于sum的值。
分析:
因为main_counter属于临界资源,可能会出现当一个线程正在执行main_counter++时,另一个线程也要执行main_counter++的情况,这样就会使main_counter的值不准确。
又线程运行顺序的不确定性(交替性),可能在一个线程执行了main_counter++后,还未执行counter[thread_num]++时,CPU便被主线程抢去,执行for(i=0;i再输出个各线程巡行的次数,及main_counter和sum的值,结果与预期的理论值不符。
3.thread的CPU占用率是多少?
为什么会这样?
197。
因为三个线程调用的函数执行的是一个死循环for(;;),使得CPU的利用率过高。
4.thread_worker()内是死循环,它是怎么退出的?
你认为这样退出好吗?
输入q回车,主线程会退出while循环,执行return()函数,结束整个程序。
自然子线程也都被迫终止,死循环也就退出了!
这样的退出不好。
5:
#include
#include
#include
#include
#include
#defineMAX_THREAD3
unsignedlonglongmain_counter,counter[MAX_THREAD];//unsignedlonglong鏄瘮long杩橀暱鐨勬暣褰€?
void*thread_worker(void*);
intmain(intargc,char*argv[])
{
inti,ch;
intnum[3];
pthread_tthid,pthread_id[MAX_THREAD]={0};
for(i=0;i{
num[i]=i;
if(pthread_create(&thid,NULL,(void*)thread_worker,&num[i])==0)
{
pthread_id[i]=thid;
//thread_worker(&i);
}
else
{
printf("threadcreaterfailed!
\n");
//exit
(1);
}
}
do
{
unsignedlonglongsum=0;
/*姹傛墍鏈夌嚎绋媍ounter鐨勫拰*/
for(i=0;i{
sum+=counter[i];
printf("%d%llu",i,counter[i]);
}
printf("\n\n%llu\n%llu\n\n",main_counter,sum);
}while((ch=getchar())!
='q');
return0;
}
void*thread_worker(void*p)
{
intthread_num;
thread_num=*((int*)p);
for(;;)
{
main_counter++;
counter[thread_num]++;
sleep
(1);
}
returnNULL;
}
实验3互斥
3.1实验目的
通过观察、分析实验现象,深入理解理解互斥锁的原理及特点
掌握在POSIX规范中的互斥函数的功能及使用方法
3.2实验要求
3.2.1实验环境要求
1.硬件
(1)主机:
PentiumIII以上;
(2)内存:
128MB以上;
(3)显示器:
VGA或更高;
(4)硬盘空间:
至少100MB以上剩余空间。
2.软件
Linux操作系统,内核2.4.26以上,预装有X-Window、vi、gcc、gdb和任意web浏览器。
3.2.2学生实验前的准备工作
准备好上节实验完成的程序thread.c。
阅读参考资料,了解互斥锁的加解锁机制及相关的系统调用。
4.3实验内容
1.找到thread.c的代码临界区,用临界区解决main_counter与sum不同步的问题。
在使用到main_counter与sum临界资源的临界区上加上p,v操作。
修改后的thread.c的代码如下:
#include
#include
#include
#include
#include
#defineMAX_THREAD3
unsignedlonglongmain_counter,counter[MAX_THREAD];//unsignedlonglong鏄瘮long杩橀暱鐨勬暣褰€?
pthread_mutex_tmutext=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;
void*thread_worker(void*);
intmain(intargc,char*argv[])
{
inti,ch;
intnum[3];
pthread_tthid,pthread_id[MAX_THREAD]={0};
for(i=0;i{
num[i]=i;
if(pthread_create(&thid,NULL,(void*)thread_worker,&num[i])==0)
{
pthread_id[i]=thid;
}
else
{
printf("threadcreaterfailed!
\n");
//exit
(1);
}
}
pthread_mutex_lock(&mutex);
do
{
unsignedlonglongsum=0;
/*姹傛墍鏈夌嚎绋媍ounter鐨勫拰*/
for(i=0;i{
sum+=counter[i];
printf("%d%llu",i,counter[i]);
}
printf("\n\n%llu\n%llu\n\n",main_counter,sum);
}while((ch=getchar())!
='q');
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutext);
return0;
}
void*thread_worker(void*p)
{
intthread_num;
thread_num=*((int*)p);
for(;;)
{
pthread_mutex_lock(&mutext);
main_counter++;
counter[thread_num]++;
sleep
(1);
pthread_mutex_unlock(&mutext);
}
returnNULL;
}
仔细阅读程序,编译程序后,先预计一下这个程序的运行结果。
运行程序。
若程序没有响应,按ctrl+c中断程序运行,然后再重新运行,如此
反复若干次,记录下每次的运行结果。
若产生了死锁,请修改程序,使其不会死锁。
4.4实验中的问题
1.你预想deadlock.c的运行结果会如何?
线程1,2会交替运行,且执行到一半会终止。
2.deadlock.c的实际运行结果如何?
多次运行每次的现象都一样吗?
为什么会这样?
交替执行!
每次执行到一半都会终止。
每次运行的结果不同。
线程终止是因为,线程的推进顺序不合法。
如果在线程1执行pthread_mutex_lock(&mutex1);语句,申请1号资源成功后,线程2又执行pthread_mutex_lock(&mutex2);语句,申请2号资源成功。
当线程1想要申请2号资源,即执行pthread_mutex_lock(&mutex2);语句或线程2想要申请1号资源,即执行pthread_mutex_lock(&mutex1);时,这两个线程将陷入无限的等待状态而产生死锁。
为避免死锁的产生,则应调换线程1或线程2对1,2号资源加锁的顺序。
即使线程1,2对1,2号资源的加锁顺序一致。
即一次性为其分配了它所需要的所有资源,避免了死锁的产生。
3.修改前补充的程序源代码
#include
#include
#include
#include
#include
#defineLOOP_TIMES10000
pthread_mutex_tmutex1=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_tmutex2=PTHREAD_MUTEX_INITIALIZER;
void*thread_worker(void*);
voidcritical_section(intthread_num,inti);
intmain(void)
{
intrtn,i;
pthread_tpthread_id=0;
rtn=pthread_create(&pthread_id,NULL,thread_worker,NULL);
if(rtn!
=0)
{
printf("pthread_createERROR!
\n");
return-1;
}
for(i=0;i{
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
critical_section(1,i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
return0;
}
void*thread_worker(void*p)
{
inti;
for(i=0;i{
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex1);
critical_section(2,i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
}
voidcritical_section(intthread_num,inti)
{
printf("Thread%d:
%d\n",thread_num,i);
}
4.修改后补充的程序源代码
#include
#include
#include
#include
#include
#defineLOOP_TIMES10000
pthread_mutex_tmutex1=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_tmutex2=PTHREAD_MUTEX_INITIALIZER;
void*thread_worker(void*);
voidcritical_section(intthread_num,inti);
intmain(void)
{
intrtn,i;
pthread_tpthread_id=0;
rtn=pthread_create(&pthread_id,NULL,thread_worker,NULL);
if(rtn!
=0)
{
printf("pthread_createERROR!
\n");
return-1;
}
for(i=0;i{
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
critical_section(1,i);
//sleep
(1);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
retu