Operating System 作业-01

简答题

3.2、内核采取一些动作以便在两个进程之间进行切换,请描述一下。

​ 总的来说,操作系统必须保存正在运行的进程的状态,恢复进程的状态。保存进程的状态主要包括CPU寄存器的值以及内存分配,上下文切换还必须执行一些确切体系结构的操作,包括刷新数据和指令缓存。

​ 进程关联是由进程的PCB来表示的,它包括CPU寄存器的值和内存管理信息等。当发生上下文切换时,内核会将旧进程的关联状态保存在其PCB中,然后装入经调度要执行的新进程的已保存的关联状态。

3.4、针对UNIX和Linux系统进程init在终止进程方面的作用,情解释一下。

​ UNIX和Linux可以通过系统调用exit()来终止进程。

​ 事实上,在正常终止时,exit()可以直接调用,也可以间接调用。父进程可以通过系统调用wait(),等待子进程的终止。系统调用wait()可用通过参数,让父进程获得子进程的退出状态;这个系统调用也返回终止子进程的标识符,这样父进程就能知道哪个子进程已经终止了。

​ 当一个进程终止时,操做系统会释放其资源。不过,它位于进程表的条目还是在的,直到它的父进程调用wait();这是因为进程表包含了进程退出的状态。当进程已经终止,但是父进程尚未调用wait(),这样的进程就被称为僵尸进程。所有进程终止时都会过渡到这种状态,但是一般而言僵尸只是短暂存在,一旦父进程调用了wait(),僵尸进程的进程标识符和它在进程表中的条目就会释放。

​ 如果父进程没用调用wait()就终止了,以至于子进程成为孤儿进程,那么Linux和UNIX系统的init()进程会定期调用wait(),以便收集任何孤儿进程的退出状态,并释放孤儿进程标识符和进程表条目。

3.7、采用如图所示的程序,确定A、B、C、D中pid的值。

1747417-20190914223920946-38117190.jpg

A = 0, B = 2603, C = 2603, D = 2600

3.10、使用如图所示程序,请解释一下行X和Y的输出是什么。

1747417-20190914224006551-1122242120.jpg

由于child是parent的副本,任何发生在child中的改变将出现在它自己的数据拷贝上,并不会影响parent父进程。因此,输出结果是:
在子进程X行处, 0、-1、-4、-9、-16
在父进程Y行处, 0、1、2、3、4

3.11、下面设计的优缺点是什么?系统层次和用户层次都要考虑。

A.对称和非对称通信:对称通信的影响是它允许发送者和接收者之间有一个集合点。缺点是阻塞发送时,不需要集合点,而消息不能异步传递。因此,消息传递系统,往往提供两种形式的同步。

B.自动和显式缓冲:自动缓冲提供了一个无限长度的队列,从而保证了发送者在复制消息时不会遇到阻塞,如何提供自动缓存的规范,一个方案也许能保存足够大的内存,但许多内存被浪费缓存明确指定缓冲区的大小。在这种状况下,发送者不能在等待可用空间队列中被阻塞。然而,缓冲明确的内存不太可能被浪费。

C.复制发送和引用发送:复制发送不允许接收者改变参数的状态,引用发送是允许的。引用发送允许的优点之一是它允许程序员写一个分布式版本的一个集中的应用程序。Java’s RMI 公司提供两种发送,但引用传递一个参数需要声明这个参数是一个远程对象。

D.固定大小和可变大小消息:涉及的太多是有关缓冲问题,带有定长信息,一个拥有具体规模的缓冲课容纳已知数量的信息缓冲能容纳的可变信息数量是未知的。考虑Windows 2000如何处理这种情况。带有定长信息(<256bytes),信息从发送者的地址空间被复制至接受进程的地址空间。更大的信息(如变长信息)使用共享内存传递信息。

编程题

3.12、使用UNIX或Linux系统,编写一个c程序,以便创建一个子进程并最终形成一个僵尸进程

1747417-20190914224635737-100295799.png

#include <stdio.h>
#include <unistd.h>

int main()
{
    pid_t pid = fork();
    if(pid < 0){
        printf("Process creation failed");
    }
    else if(pid == 0){
        printf("Parent process pid:%d\n", getpid());
    }
    else{
        printf("Parenet proces, my process is id:%d child process's id: %d\n", getpid(), pid);
        sleep(1000);  //Ensure that the child process exits before the parent process
    }
    return 0;
}

1747417-20190914224225790-1868659242.png

3.13、操作系统的pid管理器负责管理进程标识符

1747417-20190914224605827-882854377.png

#include<stdio.h>
#include<stdlib.h>

#define MIN_PID 300
#define MAX_PID 5000
#define TRUE 1
#define FALSE 0

struct PidTable{
    int pid;
    int isAvailable;
}*PID;

int allocate_map(){
    int i;
    PID = (struct PidTable*)calloc((MAX_PID - MIN_PID + 1), sizeof(struct PidTable));
    if(PID == NULL) return -1;
    PID[0].pid = MIN_PID;
    PID[0].isAvailable = TRUE;
    for(i = 1; i < MAX_PID - MIN_PID + 1; i++){
        PID[i].pid = PID[i - 1].pid + 1;
        PID[i].isAvailable = TRUE;
    }
    return 1;
}

int allocate_pid(){
    int i ;
    for(i = 0;i < MAX_PID - MIN_PID + 1; i++){
        if(PID[i].isAvailable == TRUE){
            PID[i].isAvailable = FALSE;
            return PID[i].pid;
            }
        }
    if(i == MAX_PID - MIN_PID + 1)
        return -1;
    else
        return 0;
}

void release_pid(int pid){
    PID[pid - MIN_PID].isAvailable = TRUE;
}

int main(){
    int pid;
    allocate_map();
    if((pid=allocate_pid()) != -1)
        printf("New Process Allocated Pid= %d \n", pid);

    if((pid=allocate_pid()) != -1)
        printf("New Process Allocated Pid= %d \n", pid);

    if((pid=allocate_pid()) != -1)
        printf("New Process Allocated Pid= %d \n", pid);

    if((pid=allocate_pid()) != -1)
        printf("New Process Allocated Pid= %d \n", pid);


    printf("Process %d now Releasing \n", pid);
    release_pid(pid);

    if((pid=allocate_pid()) != -1)
        printf("New Process Allocated Pid= %d \n", pid);
    return 0;
}

1747417-20190914224213894-278684729.png

3.14、Collatz猜想问题

1747417-20190914224523386-922866236.png

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

int main(int argc, char **argv)
{
    if (argc > 2){
        fprintf(stderr,"Args passed invaild!\n");
        return 1;
    }
    pid_t pid;
    pid = fork();
    if (pid < 0){
        fprintf(stderr,"Fork Failed\n");
        return 1;
    }
    else if (pid == 0){
        //child process
        int num = atoi(argv[1]);  //Convert the string to number
        printf("%d,",num);
        while (num != 1){
            if (num % 2 == 0){
                num = num / 2;
                if (num == 1) printf("%d\n",num);
                else printf("%d,",num);
            }
            else{
                num = 3*num + 1;
                printf("%d,",num);
            }
        }
    }
    else{
        //Parent process
        wait(NULL);  //Wait until the child process completed
        printf("Child Complete\n");
    }
    return 0;
}

1747417-20190914224157009-1007132965.png

3.20、利用普通管道设计一个文件复制程序filecopy

1747417-20190914224417496-84423554.png

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h> // read the number of the last error
#include <fcntl.h> // file descriptor CONSTANT mode values

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

    /*
     * File descriptor array.
     * When we create our pipe, we give pipe() this array and it will
     * put the reading[0] and writing[1] file descriptors for the pipe into it.
     */

    int pipeFds[2]; 
    int fileBytesLength;
    char buffer[100];
    char childBuffer[100];
    
    // Check if 3 arguments were supplied.
    if (argc != 3) {
      perror("Filecopy: filecopy.exe [target] [destination]. \n");
      exit(1);
    }
    
    char* srcFile = argv[1];
    char* dstFile = argv[2];

    // Attempt to create a pipe.
    if (pipe(pipeFds) < 0) {
      printf("Something went wrong creating the pipe! %s\n", strerror(errno));
      exit(1);
    }

    // Fork child process
    switch(fork()) {

      // If there was an errorforking a child process
      case -1:
        printf("Error forking child process. %s\n", strerror(errno));
        exit(1);
      
      // If the current executing process is a child process
      // Read the file from upstream parent process and write it to a new file.
      case 0: 
        close(pipeFds[1]);                                                        // Close writing end of pipe upstream.
        ssize_t num_bytes_child = read(pipeFds[0], childBuffer, sizeof(childBuffer));   // Read file contents from upstream pipe into childBuffer
        close(pipeFds[0]);                                                        // close reading upstream pipe when we're done with it

        int targetDesc = open(dstFile, O_CREAT | O_WRONLY);                                  // Open a file for writing, create file descriptor.
        write(targetDesc, childBuffer, num_bytes_child);                            // Write contents of buffer to new file descriptor.
        

      // If the current process is the parent process.
      // Read the file and send it down to the child process to write.
      default: 
        close(pipeFds[0]);                                              // close reading end of pipe downstream.
        int fileInDesc = open(srcFile, O_RDONLY);                       // Read file into file descriptor
        ssize_t num_bytes = read(fileInDesc, buffer, sizeof(buffer));   // Get number bytes to read
        write(pipeFds[1], buffer, num_bytes);                           // Write bytes to child process.
        close(pipeFds[1]);                                              // Close writing downstream pipe when we're done with it.

    }

    return 0;
}

1747417-20190914224144347-1450293381.png

转载于:https://www.cnblogs.com/lihello/p/11520495.html

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值