进程 线程.docx
《进程 线程.docx》由会员分享,可在线阅读,更多相关《进程 线程.docx(12页珍藏版)》请在冰豆网上搜索。
进程线程
西安郵電大學
操作系统课程实验
报告书
院系名称
:
计算机学院
学生姓名
:
张萌萌
专业名称
:
软件工程
班级
:
软件1001
学号
:
123456
时间
:
2012年10月25日至2012年11月5日
实验题目:
进程(补代码)
一、实验目的与要求
1.目的
●通过观察、分析实验现象,深入理解进程及进程在调度执行和内存空间等方面的特点,掌握在POSIX规范中fork和kill系统调用的功能和使用。
●通过观察、分析实验现象,深入理解线程及线程在调度执行和内存空间等方面的特点,并掌握线程与进程的区别。
●通过观察、分析实验现象,深入理解理解互斥锁的原理及特点掌握在POSIX规范中的互斥函数的功能及使用方法。
2.要求
●学习man命令的用法,通过它查看fork和kill系统调用的在线帮助,并阅读参考资料,学会fork与kill的用法。
复习C语言的相关内容
●掌握POSIX规范中pthread_create()函数的功能和使用方法.了解线程的创建等相关系统调用。
二、实验环境
Ubuntu10.10shell+Vim+gcc编译器
三.实验内容
创建进程,并且让子进程去作死循环,通过父进程去管理杀死子进程,通过调用kill()函数实现。
4、回答相关问题
补缺以下三段代码,并回答问题。
将设计分析过程和源代码写入实验报告。
(1)进程
代码:
/*POSIX下进程控制的实验程序残缺版*/
#include
#include
#include
#include
#include
#include
#defineMAX_CHILD_NUMBER10/*允许建立的子进程个数最大值*/
#defineSLEEP_INTERVAL2/*子进程睡眠时间*/
#defineDEBUG0
intproc_number=0;/*子进程的自编号,从0开始*/
voiddo_something();
intmain(intargc,char*argv[])
{
/*子进程个数*/
intchild_proc_number=MAX_CHILD_NUMBER;
inti,ch;
intfd;
pid_tchild_pid;
pid_tpid[10]={0};/*存放每个子进程的id*/
#ifDEBUG
for(i=0;i<10;i++){
printf("pid[%d]:
%d\n",i,pid[i]);
}
#endif
if(argc>1)/*命令行参数第一个参数表示子进程个数*/
{
child_proc_number=atoi(argv[1]);
child_proc_number=(child_proc_number>10)?
MAX_CHILD_NUMBER:
child_proc_number;
}
for(i=0;i{
/*填写代码,建立child_proc_number个子进程要执行
*proc_number=i;
*do_something();
*父进程把子进程的id保存到pid[i]
**/
proc_number=i;
child_pid=fork();
switch(child_pid){
case0:
pid[i]=getpid();
printf("pid[%d]:
%d\n",i,pid[i]);
do_something();
break;
case-1:
perror("fork");
exit(-1);
default:
proc_number=i;
pid[proc_number]=child_pid;
break;
}
}
#ifDEBUG
for(i=0;i<10;i++){
printf("pid[%d]:
%d\n",i,pid[i]);
}
#endif
/*让用户选择杀死进程,数字表示杀死该进程,q退出*/
while((ch=getchar())!
='q')
{
if(isdigit(ch))
{
/*填写代码,向pid[ch-'0']发信号SIGTERM,
*杀死该子进程*/
printf("\n#pid[%d]:
%dDead!
\n",ch-'0',pid[ch-'0']);
kill(pid[ch-'0'],SIGTERM);
}
}
printf("Youwillkillallprocesswhichbelongstocurrentprocess!
\n");
for(i=3;i>0;i--){
printf("%d...\n",i);
sleep
(1);
}
printf(">.
!
!
!
\n");
/*在这里填写代码,杀死本组的所有进程*/
if(-1==kill(0,SIGTERM)){
perror("kill");
exit(-2);
}
return0;
}
voiddo_something()
{
for(;;)
{
//此处需要加上\n来刷新缓冲,否则的话不会打印此句
printf("ThisisprocessNo.%danditspidis%d\n",proc_number,getpid());
sleep(SLEEP_INTERVAL);/*主动阻塞两秒钟*/
}
}
1.你最初认为运行结果会怎么样?
答:
随机创建一个进程,子进程调用do_something()函数!
会无限的循环下去!
2.实际的结果什么样?
有什么特点?
试对产生该现象的原因进行分析。
答:
通过main()函数代参数,随机的创建若干进程!
例如:
./process3创建3个进程随机的给出这3个进程的pid号,并且每次等待sleep
(2);输出一次 3个进程的运行状态。
父进程创建子进程,通过fork()函数创建!
父进程中会返回子进程的pid 把这个保存在pid[i]数组中;
3.proc_number这个全局变量在各个子进程里的值相同吗?
为什么?
答:
不相同,因为每个进程是独立的,内存会为每个进程分配独立的运行空间例如:
PCB进程块。
4.kill命令在程序中使用了几次?
每次的作用是什么?
执行后的现象是什么?
答:
执行了0-n(n<10)次,作用是杀死对应的进程。
每次执行的结果就是杀死一个进程,循环打印时,不再打印该进程的信息,归还内存分配给它的资源。
5.使用kill命令可以在进程的外部杀死进程。
进程怎样能主动退出?
这两种退出方式哪种更好一些?
答:
进程运行完退出属于正常的退出,而调用kill()是在进程运行过程中删除,这样做会破坏内存信息,我认为主动退出好些。
(1)线程
/*
*ProgramName:
2.c
*Author:
Jiajie.Chen
*Date:
2012/10/29
*Description:
OperatingSystemhomework
*POSIX下线程控制的实验程序残缺版
**/
#include
#include
#include
#include
#include
//#defineDEBUG0
#defineMAX_THREAD3/*线程的个数*/
unsignedlonglongmain_counter,counter[MAX_THREAD];
void*thread_worker(void*);
intmain(intargcm,char*argv[])
{
inti,rtn,ch;
inta[MAX_THREAD];
pthread_tthid;
pthread_tpthread_id[MAX_THREAD]={0};//存放线程ID
#ifdefDEBUG
for(i=0;iprintf("counter[%d]=%llu\n",i,counter[i]);
}
getchar();
#endif
for(i=0;i/*用pthread_create建立一个普通线程*/
/*线程ID存入pthread_id[i],线程执行*/
/*函数是thread_worker,并将i作为参数*/
/*传递给线程*/
//a[i]=i;
if(-1==(pthread_id[i]=pthread_create(&thid,NULL,thread_worker,&i))){
perror("pthread_create");
printf("pthread_id[%d]wrong!
\n",i);
}
printf("pthread_id[%d]=%d\n",i,thid);
}
do{
/*用户按一次回车执行下面的循环体一次,按Q退出*/
unsignedlonglongsum=0;
/*求所有线程的counter的和*/
for(i=0;i/*求所有的counter的和*/
sum+=counter[i];
printf("counter[%d]=%llu\n",i,counter[i]);
}
printf("main_counter/sum=%llu/%llu\n",main_counter,sum);
}while(((ch=getchar())!
='q')&&(ch!
='Q'));
return0;
}
void*thread_worker(void*p){
intthread_num;
/*将main中的i的值传递给thread_num*/
thread_num=*((int*)p);
for(;;){
#ifdefDEBUG
sleep
(1);
printf("thread_num=%d\n",thread_num);
#endif
counter[thread_num]++;//本线程的counter加1
main_counter++;//主counter加1
}
}
问题
1.你最初认为前三列数会相等吗?
最后一列斜杠两边的数字是相等,还是大于或者小于关系?
答:
不会相等!
最后一列小于.
2.最后的结果如你所料吗?
有什么特点?
对原因进行分析。
答:
没有按我想的输出结果.上面3个都是随机调用子线程所以不可能相等./号两边的数由于计算机计算的比较快,当你输出这句的时候你要输出的值其实有发生了变化.所以要加上互斥锁保证输出的时候不会反生变化.
3.thread的CPU占用率是多少?
为什么会这样?
答:
通过命令psaux查看
cpu的利用率191.创建的线程都是在一个进程里面的,所以每个进程的自加运算都是在一个进程中实现的所以cpu中只出现两./thread一个进程.
4.thread_worker()内是死循环,它是怎么退出的?
你认为这样退出好吗?
答:
thread_worker()内是死循环/它的退出是因为主线程结束了,所以子线程就会结束.
我认为这样退出不好.和那个kill()命令一样都是在程序运行中突然结束的。
(1)互斥锁
代码:
#include
#include
#include
#include
#include
#defineLOOP_TIMES10000
pthread_mutex_tmutex1=PTHREAD_MUTEX_INITIALIZER;/*用宏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;/*存放子线程的id*/
rtn=pthread_create(&pthread_id,NULL,thread_worker,NULL);
if(rtn!
=0){
printf("pthread_createERROR!
\n");
return-1;
}
for(i=0;ipthread_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;ipthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
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);
}
问题:
3.你预想deadlock.c的运行结果会如何?
答:
输出所有的数字。
4.deadlock.c的实际运行结果如何?
多次运行每次的现象都一样吗?
为什么会这样?
答:
由于产生两死锁,程序没有执行完。
多次运行一次比一次输出的少。
我认为是cpu还没有来的急释放,每次申请锁的资源,导致第2次运行的时候没申请几个资源有死锁了。