os实训课程模拟考试(大题复习)

目录

一、Linux操作系统

(1)第1关:Linux初体验

(2)第2关:Linux常用命令

[(3)第3关:Linux 查询命令帮助语句](#(3)第3关:Linux 查询命令帮助语句)

二、Linux之进程管理---(重点)

(1)第1关:获取进程常见属性

(2)第2关:进程创建操作-fork

(3)第3关:进程创建操作-vfork

(4)第4关:进程终止

三、生产者消费者问题实践

(1)第1关:生产者消费者问题实践

(2)第2关:进程互斥和同步

四、基于信号量的进程间通信

(1)第1关:信号量IPC操作考查

五、基于命名管道与信号的进程间通信

(1)第1关:命名管道与信号IPC操作考查

[六、 Linux vi/vim编辑器(难度:简单)](#六、 Linux vi/vim编辑器(难度:简单))

(1)第1关:vi/vim基本用法

(2)第2关:vi/vim工作模式切换

(3)第3关:vi/vim命令模式

(4)第4关:vi/vim底线命令模式(重点)

七、读文件系统函数(难度:简单)

(1)第1关:读文件系统函数

八、写文件系统函数(难度:中等)

(1)第1关:写文件系统函数

九、进程基础操作(难度:简单)

(1)第1关:进程基础操作考察


本篇博客的主要内容是在做大题时遇到的问题和一些总结。(具体答案看我之前的博客)

一、Linux操作系统

(1)第1关:Linux初体验
(2)第2关:Linux常用命令
  • newfile文件复制 一份到newdir目录下并命名为newfileCpy
  • cp newfile newdir/newfileCpy
(3)第3关:Linux 查询命令帮助语句
  • linux中使用man命令来查询命令的帮助文件

二、Linux之进程管理---(重点)

(1)第1关:获取进程常见属性
  • 获取进程本身的进程ID的系统调用函数是getpid()
  • 获取父进程的进程ID的系统调用函数是getppid( )
(2)第2关:进程创建操作-fork
  • 这题需要注意的地方:pid_t pid =fork();
(3)第3关:进程创建操作-vfork
  • 这题需要注意的地方:pid_t pid = vfork();
  • 子进程中输出"Children"字符串(提示:需要换行)
(4)第4关:进程终止
  • 用这个注册函数:atexit()on_exit()调用成功返回0;调用失败返回一个非零值。
cs 复制代码
 void exit(){
        printf("%d",getpid());
    }
	if(atexit(exit)){
        
    }

三、生产者消费者问题实践

(1)第1关:生产者消费者问题实践
  • 观察题目代码给出的生产者函数。根据这个来写!!

  • sem_t empty; :类似等待一个信号(生产)

  • sem_t full; :类似等待一个信号(消费)

  • sem_wait(&empty);

  • sem_wait(&full);


    (在每一个操作时和释放时都要记得加锁和解锁)

  • 加锁 pthread_mutex_lock(&mutex);
  • 释放锁 pthread_mutex_unlock(&mutex);

锁对象:pthread_mutex_t mutex;


  • 设置一个参数(仿照生产者函数)int nextc = 0;

  • 先给一个等待消费条件:sem_wait(&full);

  • 再加锁:pthread_mutex_lock(&mutex);

  • 意思是:从之前生产了的东西拿东西出来消费:nextc=buffer[out];

  • 与生产者函数中用到的一样:int out = 0;

  • 这个跟着改:printf("Consume one message :%d\n", nextc);

  • fflush(stdout); //printf后请一定调用这句刷新输出缓存out = (out + 1) % SIZE;

  • out = (out + 1) % SIZE; (这个跟生产者函数一样,对着改就行)

  • pthread_mutex_unlock(&mutex); ------> 再解锁

最后记得给一个消费完的信号:sem_post(&empty); 。意思其实就是消费完,给一个叫"空"的信号。


具体的答案《消费:Consumer()函数》

cs 复制代码
void *Consumer()
{
    // ============================= begin ======================

	//请补充消费者线程函数代码
    int nextc = 0;
    int i = 0;
	for(; i < 10; ++i)
	{  
		int time = rand() % 10 + 1;
        usleep(time*100000); 
        sem_wait(&full); 
		pthread_mutex_lock(&mutex);
		nextc=buffer[out];
		printf("Consume one message:%d\n", nextc);
		fflush(stdout);//printf后请一定调用这句刷新输出缓存
		out = (out + 1) % SIZE;
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
	}


 // ============================= end ========================

}

对比题目提供的《生产函数:Producer()》

cs 复制代码
int in = 0;
int out = 0;
int buffer[SIZE];
sem_t empty;
sem_t full;
pthread_mutex_t mutex;

void *Producer()
{
    int nextp = 0;
    int i = 0;
	for(; i < 10; ++i)
	{  
		int time = rand() % 10 + 1;
        usleep(time*100000); 
        sem_wait(&empty); 
		pthread_mutex_lock(&mutex);
		buffer[in] = nextc;
		printf("Produce one message:%d\n", nextp);
		fflush(stdout);//printf后请一定调用这句刷新输出缓存
		in = (in + 1) % SIZE;
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&full);
	}
}
(2)第2关:进程互斥和同步

(这个就简单了!!结合上面学的东西,以及仿照这个题目女儿的"苹果"消费函数写就好)

  • 把消费等待的信号换成"orange(桔子)"
  • 把printf(....)输出换一下就好了
  • 儿子消费函数答案
cs 复制代码
void *Son()
{
    // ============================== begin ===========================

	//请添加儿子线程的函数代码
    while(1)
	{
		int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time * 100000);        
		sem_wait(&orange); 
		pthread_mutex_lock(&mutex);
		printf("儿子取了一个桔子\n") ;
        fflush(stdout);
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
	}

    // ============================== end ==============================
}

四、基于信号量的进程间通信

(1)第1关:信号量IPC操作考查
  • 搞清楚函数:semctl(int semid,int semnum,int cmd,...);
  • semid要操作的信号量集合:(题目中给出变量:"int semid; ")
  • semnum集合中信号量的编号(题目中就是:"i")
  • cmd执行的操作:(题目中有提示:``#define GETVAL 获取信号量的值返回信号的值``)

具体答案如下:

(此代码不严谨!!因为没有判断是否函数调用成功!但是满足评测要求)

cs 复制代码
 for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
    {
        // =================================== begin ===============================

        /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
 
        // 注意:getval_arg.val 在这里不需要设置,因为 GETVAL 不使用它  
        int x = semctl(semid, i, GETVAL);  

        printf("Semaphore %d, value %d\n", i, x); 

            // =================================== end ===============================

        }

更完整、更严谨的答案:
(记得还要在顶部导入包:#include <stdlib.h> //以使用exit函数)

cs 复制代码
for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
    {
        // =================================== begin ===============================

        /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
 
        // 注意:getval_arg.val 在这里不需要设置,因为 GETVAL 不使用它  
        int x = semctl(semid, i, GETVAL);  
        if (x == -1) {  
        printf("GETVAL for semaphore %d failed (%d)\n", i, errno);  
        exit(EXIT_FAILURE);  
    }
        printf("Semaphore %d, value %d\n", i, x); 

            // =================================== end ===============================

        }

五、基于命名管道与信号的进程间通信

(1)第1关:命名管道与信号IPC操作考查

没啥好说的,不会的操作系统考试就靠记呗!!

  • **sleep(1);**休眠1秒
  • 打开读通道------> open("FIFO",O_RDONLY);
  • 打开写通道------> open("FIFO",O_WRONLY);
  • 开始写------>write(fd,"heool0penEuler",1);

答案如下:

cs 复制代码
 if(pid==0)
    {
        // ============================= begin =========================
        /*子进程打开读管道,随后关闭管道*/
        int fd;
        fd = open("FIFO",O_RDONLY);  /*rd->only 写*/
        /*关闭*/
        close(fd);
    }
    else
    {
        
        /*父进程打开写通道,休眠1秒,尝试写入*/
        int fd;
        fd = open("FIFO",O_WRONLY);  /*wr->only 写*/
        int ret;
        sleep(1); /*休眠1秒*/
        /*写入*/
        ret = write(fd,"heool0penEuler",1);

        // ============================= end =========================
    }

六、 Linux vi/vim编辑器(难度:简单)

(注意这类题目在操作之前需要初始化任务环境)

(1)第1关:vi/vim基本用法
(2)第2关:vi/vim工作模式切换
  • wq :保存并退出
  • i:插入
(3)第3关:vi/vim命令模式
  • dd:删除
  • yy:复制
  • p:粘贴
(4)第4关:vi/vim底线命令模式(重点)
  • 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2。 :1,$s/word1/word2/g
  • 将文件第2-5行内容另存为oldFileCpy.txt文件:2,5 w oldFileCpy.txt

七、读文件系统函数(难度:简单)

(1)第1关:读文件系统函数

(此题注意:知道read()函数是啥就行了。其次知道其返回值和其函数的参数)

  • 函数原型:read(int fd, void *buf, size_t count);
  • fd:看上文(读文件的地址)
  • *buf:字符数组缓冲区的位置
  • 最后这个size_t count:就是读到的全部字符的个数------>sizeof(buffer)-1
cs 复制代码
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define rwmode 0
int main()
{
    int fd;
    char buffer[1024];
    int n;
    fd = open("/data/workspace/myshixun/case1/testFIle", rwmode);
    if (fd < 0)
    {
        printf("Open file error!\n");
        exit(1);
    }
    else
        printf("open testFIle ok!\n");
    //-------------begin----------------------  
    //请使用read函数将其读入buffer中
    n = read(fd,buffer,sizeof(buffer)-1);
    //--------------end----------------------  
    buffer[n] = '\0';
    printf("%s\n", buffer);
    close(fd);
    return 0;
}

八、写文件系统函数(难度:中等)

(1)第1关:写文件系统函数

(这题其实就是一个综合。先用read()读函数,再用write()写函数)

  • 函数原型:ssize_t write(int fd, const void *buf, size_t count);

  • 读的文件的地址题目也给出:int resource_fd

  • char buffer[FILESIZE]:字符数组

  • #define FILESIZE 1024 (该字符数组最大容量,也是题目要求读取的量)

  • 所以:(read(resource_fd,buffer,FILESIZE ))>0,因为读到了就要返回得到的个数。

  • char buffer[FILESIZE], *p; p = buffer; :要写入的字符数组信息地址在p

  • 写的目的文件地址题目也给出了:int destination_fd

  • 具体要写的字符个数(前面被赋值):readbytes = read(resource_fd,buffer,FILESIZE)

  • 所以:(writebytes = write(destination_fd,p,readbytes))>0,因为写到了就要返回个数

综合解答:

cs 复制代码
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define resource_mode 0
#define destination_mode 0774
#define FILESIZE 1024

int main(int argc, char *argv[])
{
    int resource_fd, destination_fd;
    char buffer[FILESIZE], *p;
    int readbytes, writebytes;
    if (argc != 3)
    {
        printf("Usage:copy from resource file to destination file\n %s src_file dest_file\n", argv[0]);
        exit(0);
    }
    if ((resource_fd = open(argv[1], resource_mode)) == -1)
    {
        perror("Can't open source file");
        exit(0);
    }
    if ((destination_fd = creat(argv[2], destination_mode)) == -1)
    {
        perror("Can't create destination file");
        exit(0);
    }
    // ======================= begin =======================================

    // 请使用read函数读取前1024字节的内容读到缓冲区buffer中
    while ((readbytes = read(resource_fd,buffer,FILESIZE))>0)

    // ========================== end =======================================
    {
        p = buffer;
        if ((readbytes == -1) && (errno != EINTR))
            break;
        else if (readbytes > 0)
        {
            // ======================= begin =======================================

            // 请使用write函数读取到的前1024字节的内容写到目的文件中
            while ((writebytes = write(destination_fd,p,readbytes))>0)

            // ========================== end =======================================
            {
                if ((writebytes == -1) && (errno != EINTR))
                    break;
                else if (writebytes == readbytes)
                    break;
                else if (writebytes > 0)
                {
                    p += writebytes;
                    readbytes -= writebytes;
                }
            }
            if (writebytes == -1)
                break;
        }
    }
    close(resource_fd);
    close(destination_fd);
    return 0;
}

九、进程基础操作(难度:简单)

(1)第1关:进程基础操作考察

(这一关没啥好说的,难度很简单)

  • 了解fork()函数即可
  • 注意空格的输出(父、子进程都一样):printf("bye! ");
cs 复制代码
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
  /*请开始填写*/
  pid_t pid =fork();
  if(pid==0){
    printf("bye! ");
  }
  else if(pid>0){
    printf("bye! ");
  }
      return 0;
}
相关推荐
大聪明-PLUS2 分钟前
C++中变量的声明和初始化
linux·嵌入式·arm·smarc
Ziegler Han7 分钟前
《升维》阅读笔记:在不确定的世界里,如何做出高确定性的决策
笔记·《升维》
工程师平哥11 分钟前
APE-01 新建工程
笔记·嵌入式硬件
被制作时长两年半的个人练习生23 分钟前
如何调试llama.cpp及判断是否支持RVV
linux·服务器·llama
泓博23 分钟前
Android摇一摇
笔记
赖small强35 分钟前
【音视频开发】Linux V4L2 (Video for Linux 2) 驱动框架深度解析白皮书
linux·音视频·v4l2·设备节点管理·视频缓冲队列·videobuf2
四谎真好看41 分钟前
Linux 附录二,实验一
linux·运维·服务器·学习笔记
神秘的土鸡43 分钟前
Linux中使用Docker构建Nginx容器完整教程
linux·nginx·docker
Molesidy1 小时前
【Embedded Development】BootROM的详细分析以及Linux开发板的上电启动流程初步分析
linux