操作系统概念-第四章
本文最后更新于一年前或更久前,其中的信息可能已经有所发展或是发生改变。

Tips:此为⬛⬛⬛⬛⬛⬛大学⬛⬛⬛⬛⬛⬛⬛学院2019级《操作系统原理》课程中的部分课程作业题目解析和展示

4.2 内核级别和用户级别的线程的两个区别是什么?在什么情况下一个类型比另一个好?

1.用户级别的线程被提供与用户级别,高于内核而且管理不需要内核的支持,因为他们是被用户执行而内核并不能意识到他们的存在。一般他们是更小的,更简单,更快速被创建的,而且他们比其他组件可以更容易地被管理,而且他们的同步中不涉及内核。

2.操作系统直接支持和管理内核线程。因为它们是由操作系统处理的,所以内核负责线程管理。如果一个线程执行阻塞操作,可以在另一个处理器上调度同一进程的另一个线程,但是这些线程创建速度较慢。

所以:

​ 内核级别线程直接被内核支持而用户级别的线程对内核来说是未知的。

​ 内核线程创建更慢而且维护他们的副本的成本更高,因为他们需要更多资源

一般内核线程更适合高权限的任务,比如那些需要系统资源的而用户线程更适合低等级不是很必要被内核管理的任务。

4.4 当一个线程被创建时,什么资源被使用了?怎么把他们和其他被使用的资源区分开,当一个线程被创建的时候?

当一个线程被创建,那些线程上下文的寄存器组,栈,和私有存储空间被创建。

1)寄存器组是上下文切换期间存储的存储位置;

2)本地堆栈用于记录过程调用参数、返回值和返回地址;

3)线程私有存储被各种运行时库和动态存储所使用(那些DLL文件)。

当一个进程被创建,用于程序存储数据的内存空间和县城存储空间将被分配。

4.7 在什么情况下,在一个单处理器系统中一个使用多个内核线程的多线程解决方案会比一个线程的表现得更好?

因为一个内核线程会出现页面错误,所以可以切换到另一个内核线程,以一种有用的方式使用交错时间。

而当发生页面错误时,单线程进程将无法执行有用的工作。

因此,在程序可能遭受频繁的页面错误或必须等待其他系统事件的情况下,多线程解决方案比单处理器系统具有更好的性能。

4.8 下列哪个程序状态组件是在多线程进程中跨线程共享的?

a.寄存器值、b.堆内存、c.全局变量、d.栈内存

BC

4.9 使用多个用户级线程的多线程解决方案能否在多处理器系统上获得比在单处理器系统上更好的性能?解释一下。

多线程系统由多个用户级线程组成,这些线程不能同时使用多处理器系统中的不同处理器。操作系统只感知单个进程,不会将该进程的不同线程调度到不同的处理器上。因此,在多处理器系统上执行多个用户级线程没有任何好处。

4.14 有两个双核处理器的系统有四个处理器可用于调度……

Q:有两个双核处理器的系统有四个处理器可用于调度。一个CPU密集型应用程序正在这个系统上运行。所有的输入都在程序启动时执行,此时必须打开一个文件。类似地,所有输出都在程序终止之前执行,此时程序结果必须写入单个文件。在启动和终止之间,程序完全受CPU限制。您的任务是通过对该应用程序进行多线程处理来提高其性能。应用程序运行在使用一对一线程模型的系统上(每个用户线程映射到一个内核线程)

1)创建和阻塞系统调用一样多的线程是很重要的,因为线程将被阻塞。创建额外的线程没有任何好处。因此,创建一个用于输入的线程和一个用于输出的线程。

2)为应用程序的CPU密集型部分创建了四个线程。由于具有两个双核处理器的系统有4个可用处理器,较少的线程将浪费处理资源,任何大于4的线程都将无法运行。线程的数量应该和处理核的数量一样多。

*4.15 思考下面的代码段:

pid t pid;
pid = fork();
if (pid == 0) { /* child process */
    fork();
    thread create( . . .);
}
fork();

###### a.多少个独立的进程被创建了?

###### b.多少个独立的线程被创建了?

a.6个。设父程序为p0,在第二行代码fork()创建了子程序p1,然后在if语句中,子程序的fork()返回值为0,所以满足条件,p1的fork()创建了第二个子程序p2,在最后一行代码中,fork()被p0,p1,p2分别执行,所以又有三个新的独立程序被创建。共计6个。

b.8个。也就是说,有两个双线程的进程,其余为单线程进程。

```c
1) after first fork():

   |-------------------  child of p0 [p1]
---|-------------------  parent      [p0]

2) after second fork():

       |---------------  child of p1 [p2] //子程序的fork()返回值为0
   |---|---------------              [p1]
---|-------------------              [p0]

3) after pthread_create():

            -----------  thread 1 of p2 [p2t1] //p2也是子程序,满足if的条件
       |---/-----------  thread 0 of p2 [p2t0]
       |    -----------  thread 1 of p1 [p1t1]
   |---|---/-----------  thread 0 of p1 [p1t0]
---|-------------------                 [p0]

4) after third fork():

         |------------ child of p2 [p5]
         |      ------             [p2t1]
       |-|-----/------             [p2t0]
       |   |---------- child of p1 [p4]
       |   |    ------             [p1t1]
   |---|---|---/------             [p1t0]
   |     |------------ child of p0 [p3]
---|-----|------------             [p0]
             //最终所有的程序都执行最后的fork()

参考资料:multithreading – How many processes and threads will be created? – Stack Overflow

4.16 如第4.7.2节所述,Linux不区分进程和线程。相反,Linux以相同的方式处理两者,允许一个任务更类似于一个进程或线程,这取决于传递给clone()系统调用的一组标志……

Q:如第4.7.2节所述,Linux不区分进程和线程。相反,Linux以相同的方式处理两者,允许一个任务更类似于一个进程或线程,这取决于传递给clone()系统调用的一组标志。然而,其他操作系统(如Windows)对待进程和线程的方式是不同的。通常,这样的系统使用一种表示法,其中进程的数据结构包含指向属于该进程的独立线程的指针。对比这两种建模内核中进程和线程的方法。

像Linux这样的系统以相同的方式建模进程和线程,这些操作系统代码可能很简单。Linux操作系统中的调度器认为不同的进程和线程是平等的,不需要特殊的代码来测试与每个进程相结合的线程。此外,创建线程的开销更少。其他操作系统(如Windows XP和Solaris)区别对待进程和线程,增加了一些额外的复杂性,以确定哪个线程对应哪个进程并执行相关的计费任务。

4.17 图4.16所示的程序使用Pthreads API。程序在LINE C和LINE P的输出是什么?

LINE C:5

LINE P:0

4.21 编写一个多线程程序,计算一系列数字的各种统计值。这个程序将在命令行中传递一系列数字,然后创建三个独立的工作线程。一个线程将确定这些数字的平均值,第二个线程将确定最大值,第三个线程将确定最小值……

Q:编写一个多线程程序,计算一系列数字的各种统计值。这个程序将在命令行中传递一系列数字,然后创建三个独立的工作线程。一个线程将确定这些数字的平均值,第二个线程将确定最大值,第三个线程将确定最小值。例如,假设你的程序传递了一个整数90 81 78 95 79 72 85,程序将报告 ‘The average value is 82 The minimum value is 72 The maximum value is 95’代表平均值、最小值和最大值的变量将全局存储。工作线程将设置这些值,一旦工作线程退出,父线程将输出这些值。(我们可以通过创建其他线程来确定其他统计值,比如中值和标准差来扩展这个程序。)

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

int avg, max, min; //全局变量存储平均值、最大值、最小值 
int count; //用于统计参数总数 

void *runner1(void *param);
void *runner2(void *param);
void *runner3(void *param);

int main(int argc, char **argv){
   count = argc-1; //参数总数 

   pthread_t tid1, tid2, tid3; //创建线程的标识符
   pthread_attr_t attr1, attr2, attr3; //创建线程的属性

   if (argc <= 1){ //没有输入参数,报错 
    fprintf(stderr, "no numbers!n");
    return -1;
   } 

   /*创建一个数组存参数,注意要把argv[0]不存入,因为它是该程序本身,后面的才是参数*/
   int *arr = (int *)malloc(sizeof(int)*(count));
   if(arr == NULL){
    fprintf(stderr, "malloc() failed!n");
    return -1;
   } 

   int i;
   for (i = 0; i < count; i++){
    arr[i] = atoi(argv[i+1]); 
   }

   /*设置线程属性*/
   pthread_attr_init(&attr1);
   pthread_attr_init(&attr2);
   pthread_attr_init(&attr3);

   /*创建线程*/
   pthread_create(&tid1, &attr1, runner1, arr);
   pthread_join(tid1, NULL);  //等待线程1完成 

   pthread_create(&tid2, &attr2, runner2, arr);
   pthread_join(tid2, NULL);

   pthread_create(&tid3, &attr3, runner3, arr);
   pthread_join(tid3, NULL);

   printf("The average value is %dn", avg);
   printf("The minimum value is %dn", min);
   printf("The maximum value is %dn", max);

   free(arr); //释放内存

   return 0;
}

void *runner1(void *param){ //此线程算平均值 
   int *arr = (int *)param;
   int sum = 0;
   int i;

   for(i = 0; i<count; i++){
    sum += arr[i];
   }  

   avg = sum/count;

   pthread_exit(0);  //线程终止回到父线程 
}

void *runner2(void *param){ //此线程算最大值
   int *arr = (int *)param;
   max = arr[0]; 
   int i;

   for(i = 1; i<count; i++){
    if(arr[i] > max){
        max = arr[i];
    }
   }  

   pthread_exit(0);  //线程终止回到父线程 
}

void *runner3(void *param){ //此线程算最小值
   int *arr = (int *)param;
   min = arr[0]; 
   int i;

   for(i = 1; i<count; i++){
    if(arr[i] < min){
        min = arr[i];
    }
   }  

   pthread_exit(0);  //线程终止回到父线程 
}

参考资料:pthread详解_networkhunter的博客-CSDN博客

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇