操作系统实验报告

 

实验2进程


2.1实验目的


 通过观察、分析实验现象,深入理解进程及进程在调度执行和内存空间等方面的特点,
 

掌握在POSIX规范中fork和kill系统调用的功能和使用。

 2.2实验要求

2.2.1实验环境要求

1.硬件

(1)主机:PentiumIII 以上;

(2)内存:128MB;

(3)显示器:VGA;

(4)硬盘空间:至少100MB以上剩余空间。

2.软件

操作系统:Linux;

内核:2.4.26以上

预装有:GuakeTerminal,Google浏览器

2.2.2学生实验前的准备工作

了解man命令中fork和kill的用法,查阅参考资料,学会fork与kill,复习C语言的相关内容。

2.3实验内容


通读下列代码:

 

/* 
* POSIX 下进程控制的实验程序残缺版 
*/ 
#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h> 
#include <signal.h>
#include <ctype.h> 
/* 允许建立的子进程个数最大值 */
#define MAX_CHILD_NUMBER 10 
/* 子进程睡眠时间 */
#define SLEEP_INTERVAL 2 
int proc_number=0; /* 子进程的自编号,从0开始 */
void do_something(); 
main(int argc, char* argv[])

int child_proc_number = MAX_CHILD_NUMBER; /* 子进程个数 */
int i, ch; 
pid_t child_pid; 
pid_t pid[10]={0}; /* 存放每个子进程的id */ 
if (argc > 1)

/* 命令行参数中的第一个参数表示建立几个子进程,最多10个 */ 
child_proc_number = atoi(argv[1]); 
child_proc_number
= (child_proc_number > 10) ? 10 : child_proc_number;

for (i=0; i<child_proc_number; i++)

/* 在这里填写代码,建立child_proc_number个子进程
* 子进程要执行
* proc_number = i; 
* do_something();
* 父进程把子进程的id保存到pid[i] */



/* 让用户选择杀死哪个进程。输入数字(自编号)表示杀死该进程
* 输入q退出 */
while ((ch = getchar()) != 'q')

if (isdigit(ch)) 

/* 在这里填写代码,向pid[ch-'0']发信号SIGTERM, 
* 杀死该子进程 */ 


 }



/* 在这里填写代码,杀死本组的所有进程 */ 
return;

void do_something()

for(;;)

/* 打印子进程自编号。为清晰,在每个号码前加“号码+3”个空格
* 比如号码是1,就打印" 1" */
printf("This is process No.%*d\n",
proc_number+3, 
proc_number); 
sleep(2); /* 主动阻塞两秒钟 */




先猜想一下这个程序的运行结果。假如运行“./process 20”,输出会是什么样?
然后按照注释里的要求把代码补充完整,运行程序。可以多运行一会儿,并在
此期间启动、关闭一些其它进程,看process 的输出结果有什么特点,记录下这个结果。
开另一个终端窗口,运行“ps aux|grep process”命令,看看process 究竟启动了多少个进程。回到程序执行窗口,按“数字键+回车”尝试杀掉一两个进程,再到另一个窗口看进程状况。
按q 退出程序再看进程情况。
 
2.4 实验报告
回答下列问题,写入实验报告。




1. 你最初认为运行结果会怎么样?
答:从0到9顺序打印,按下数字回车后杀死相对应进程,输入q回车后,则退出程序
2. 实际的结果什么样?有什么特点?试对产生该现象的原因进行分析。
答:


如图所示
实验结果与预期结不相同,产生的子进程数最多为10个,当产生小于10个, 则产生10个,大于10个,直接产生10个,随机输出0~9号进程,循环输 出。

输入数字键回车后,杀死该数字所对应的进程,输入q回车后,杀死所有进程,退出程序。


3. proc_number 这个全局变量在各个子进程里的值相同吗?为什么?
 

答,相同,子进程的资源相互独立,互不影响。
 

4. kill 命令在程序中使用了几次?每次的作用是什么?执行后的现象是什么?
答:kill命令在程序中使用了2次,kill(pid[ch-'0'],SIGTERM)和kill(0,SIGTERM); 第一次是杀死该进程号pid[ch-‘0’],输入进程号回车后,执行后接下来的结果中不会有该进程号,

第二次是杀死本组所有进程。即主进程以及它创建的所有子进程。执行后程序退出,进程结束。用另一个终端打开,使用命令ps -a,查看终端下运行的进程。
 

5. 使用kill 命令可以在进程的外部杀死进程。进程怎样能主动退出?这两种退出方式哪种更好一些?
 

答:进程在main函数中return,或调用exit()函数都可以正常退出,而使用kill命令则是异常退出。正常退出比较好,若在子进程退出前使用kill命令杀死其父进程,则系统会让init进程接管子进程。当用kill命令使得子进程先于父进程退出时,而父进程又没有调用wait函数等待子进程结束,子进程处于僵死状态,并且会一直保持下去,直到系统重启。子进程处于僵死状态时,内核只保存该进程的必要信息以被父进程所需,此时子进程始终占着资源,同时减少了系统可以创建的最大进程数,使用return正常退出更好一些
 

6. 把你的程序源代码附到实验报告后。 
   代码:

#include <stdio.h>  

#include <sys/types.h>  

#include <unistd.h>  

#include <signal.h>  

#include <ctype.h>  

/* 允许建立的子进程个数最大值 */  

\#define MAX_CHILD_NUMBER    10  

/* 子进程睡眠时间 */  

#define SLEEP_INTERVAL        2  

int proc_number=0; /* 子进程的自编号,从0开始 */  

void do_something();  

int main(int argc, char* argv[])  

{  

    int child_proc_number = MAX_CHILD_NUMBER;    /* 子进程个数 */  

    int i, ch;  

    pid_t child_pid;  

    pid_t pid[10]={0};    /* 存放每个子进程的id */  

          if (argc > 1)  

    {  

        /* 命令行参数中的第一个参数表示建立几个子进程,最多10个 */  

        child_proc_number = atoi(argv[1]);  

        child_proc_number   

            = (child_proc_number > 10) ? 10 : child_proc_number;   

    }  

    for (i=0; i<child_proc_number; i++)  

        {  

        child_pid = fork();  

        if(child_pid > 0)  

        {  

            pid[i] = child_pid;   

         }  

        else if(child_pid == 0)  

        {  

            proc_number = i;  

            do_something();  

        }  

        else  

        {  

            perror("fail to fork!\n");   

        }  

         

        /* 在这里填写代码,建立child_proc_number个子进程  

        * 子进程要执行       

        *    proc_number = i;  

        *    do_something();  

        * 父进程把子进程的id保存到pid[i] */  

    }  

 /* 让用户选择杀死哪个进程。输入数字(自编号)表示杀死该进程  

    * 输入q退出 */  

    while ((ch = getchar()) != 'q')  

    {  

        if (isdigit(ch))  

        {  

            kill(pid[ch-'0'], SIGTERM);  

            /* 在这里填写代码,向pid[ch-'0']发信号SIGTERM,  

            * 杀死该子进程 */  

        }  

          

    }  

/* 在这里填写代码,杀死本组的所有进程 */  

    kill(0, SIGTERM);  

    return 0;           

}  

void do_something()  

{  

    for(;;)  

    {  

        printf("This is process No.%d and its pid is %d\n",  proc_number,  getpid());  

        sleep(2); /* 主动阻塞两秒钟 */  

    }  

}  

 

 

实验3线程


3.1实验目的
 

通过观察、分析实验现象,深入理解线程及线程在调度执行和内存空间等方
 

面的特点,并掌握线程与进程的区别。

掌握在POSIX规范中pthread_create()函数的功能和使用方法

 

3.2实验要求
 

3.2.1实验环境要求
 

 

1.硬件

(1)主机:PentiumIII 以上;

(2)内存:128MB;

(3)显示器:VGA;

(4)硬盘空间:至少100MB以上剩余空间。

2.软件

操作系统:Linux;

内核:2.4.26以上

预装有:GuakeTerminal,Google浏览器

 

 

3.2.2学生实验前的准备工作
 

阅读参考资料,了解线程的创建等相关系统调用。

 

3.3实验内容
 

通读下列代码:

/*
* POSIX 下线程控制的实验程序残缺版1.27 */


#include<stdio.h>
#include <sys/types.h>
#include<unistd.h>
#include <ctype.h>
#include<pthread.h>


#defineMAX_THREAD 3 /* 线程的个数*/
unsignedlong long main_counter, counter[MAX_THREAD]; /* unsignedlong
long是比long还长的整数*/
void*thread_worker(void*);


intmain(int argc, char* argv[])


{
int i, rtn, ch;
pthread_t pthread_id[MAX_THREAD] = {0};/* 存放每个线程的id*/

for(i=0; i<MAX_THREAD; i++)

{
/* 在这里填写代码,用pthread_create建一个普通的线程,

*线程id存入pthread_id[i],
}
* 线程执行的函数是thread_worker,并i作为参数传递给线程*/
/* 用户按一次回车执行下面的循环体一次。按q退出*/
do
{


unsignedlong long sum = 0;
/* 求所有线程的counter的和*/
for(i=0; i<MAX_THREAD; i++)


{
sum += counter[i];
printf("%llu ", counter[i]);


}

 printf("%llu/%llu",main_counter, sum);
}
while ((ch = getchar()) != 'q');


 return0;
}

void*thread_worker(void* p)
{
int thread_num;

/*在这里填写代码,把main中的i的值赋给thread_num*/

for(;;)/* 无限循环*/
{


 counter[thread_num]++;/* 本线程的counter加一*/

main_counter++;/* 主counter加一*/
}
}
 

按照注释里的要求把代码补充完整,正确编译程序后,先预计一下这个程序的
运行结果。具体的结果会是什么样?

运行程序。开另一个终端窗口,运行“psaux”命令,看看thread的运行情
况,注意查看thread的CPU占用率,并记录下这个结果。

3.4实验报告
 

回答下列问题,写入实验报告。

1.你最初认为前三列数会相等吗?最后一列斜杠两边的数字是相等,还是大于或者小于关系?

 

答,最初我认为三列数字相等,最后一列斜杠两边的数字是也会相等的。
 

2.最后的结果如你所料吗?有什么特点?试对原因进行分析。

答:

 

最后结果有所差异,前三个值不会相等,前三个值之和等于sum值,main_counter值小于sum值,但二者相差不大。

分析:三个线程在共同争取运行thread_worker()函数,pthread_id[i]执行后main_counter++,比如在执行pthread_id[0]后pthread_id[1]又申请执行thread_worker()函数,这时候main_counter值就少加一次了,所以会发生main_counter值比sum值小的情况。


3.thread 的CPU占用率是多少?为什么会这样?

答:cpu占用率160,因为线程是无限死循环,所以占用率高。
4.thread_worker()内是死循环,它是怎么退出的?你认为这样退出好吗?

答:输入q,退出循环。子进程也会退出,这样退出不好。

5.把你的程序源代码附到实验报告后。并请保留源代码,下一个死锁实验需要使用

代码:

 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值