linux试验报告.docx

上传人:b****5 文档编号:6609229 上传时间:2023-01-08 格式:DOCX 页数:14 大小:20.37KB
下载 相关 举报
linux试验报告.docx_第1页
第1页 / 共14页
linux试验报告.docx_第2页
第2页 / 共14页
linux试验报告.docx_第3页
第3页 / 共14页
linux试验报告.docx_第4页
第4页 / 共14页
linux试验报告.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

linux试验报告.docx

《linux试验报告.docx》由会员分享,可在线阅读,更多相关《linux试验报告.docx(14页珍藏版)》请在冰豆网上搜索。

linux试验报告.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1