os实训课程模拟考试(8~13)

基于信号量的进程间通信

信号量IPC操作考查

编程要求

根据提示,在右侧编辑器补充代码,了解OpenEuler系统如何使用信号量进行IPC通信,代码中先用sem_read_array[]数组存储数据,并进行信号量与数据的输出,我们需要补充代码使用semctl函数输出一样的数据。

#include <errno.h>
 #define MAX_SEMAPHORES  5
#include <stdio.h>
 #include <sys/types.h>
 #include <sys/sem.h>
 #include <errno.h>
 #include <stdlib.h>   //以使用exit函数
 #define MAX_SEMAPHORES  5
 int main(int argc,char *argv[])
{
    int i, ret, semid;
    unsigned short sem_array[MAX_SEMAPHORES];
    unsigned short sem_read_array[MAX_SEMAPHORES];

    union semun
    {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
    } arg;
    semid = semget( IPC_PRIVATE, MAX_SEMAPHORES,IPC_CREAT | 0666 );

    if (semid != -1)

    {
        for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
        {
            sem_array[i] = (unsigned short)(i+1);
        }
        arg.array = sem_array;
        ret = semctl( semid, 0, SETALL, arg);
        if (ret == -1) 
            printf("SETALL failed (%d)\n", errno);
        arg.array = sem_read_array;
        ret = semctl( semid, 0, GETALL, arg );
        if (ret == -1) 
            printf("GETALL failed (%d)\n", errno);
        for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
        {
           printf("Semaphore %d, value %d\n", i, sem_read_array[i] );

        }


    for (i = 0; i < MAX_SEMAPHORES; i++) {  
    union semun getval_arg;  
    // 注意:getval_arg.val 在这里不需要设置,因为 GETVAL 不使用它  
    int sem_value = semctl(semid, i, GETVAL, getval_arg);  
    if (sem_value == -1) {  
        printf("GETVAL for semaphore %d failed (%d)\n", i, errno);  
        exit(EXIT_FAILURE);  
    }  
    printf("Semaphore %d, value %d\n", i, sem_value);  
}


        ret = semctl( semid, 0, IPC_RMID );
    }
    else
        printf("Could not allocate semaphore (%d)\n", errno);
    return 0;
}

 记得引入<stdlib.h>包,以便使用exit函数

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

命名管道与信号IPC操作考查

编程思路

根据提示,在右侧编辑器补充代码,使用SIGPIPE信号进行记录,读通道关闭后写通道写入。首先子进程以读的方式打开管道,然后父进程以写的方式打开管道,父进程当即睡眠1秒,子进程关闭读管道,当父进程休眠完成后开始写入,会发出写入失败信号。

#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/types.h>

void handler(int sig)
{
    printf("sig=%d\n",sig);

}
int main(void)
{
    int j;
    signal(SIGPIPE,handler);//在reader中止之后写Pipe的时候发送
    unlink("FIFO");
    mkfifo("FIFO",0644);
    pid_t pid;
    pid=fork();
    if(pid==0)
    {
        /*子进程打开读管道,随后关闭管道*/
       int fd;
        fd = open("FIFO",O_RDONLY);
        close(fd);
    }
    else
    {
        /*父进程打开写通道,休眠1秒,尝试写入*/
        int fd;
        fd = open("FIFO",O_WRONLY);
        int ret;
        sleep(1);
         ret = write(fd,"heoolOpenEuler",14);
    }
}

 

Linux vi/vim编辑器

第1关:vi/vim基本用法

编程要求

本关任务是学会如何启动和退出vi/vim编辑器。

注意:在执行本关任务前,首先执行如下命令来初始化任务环境

  1. rm -fr /root/oldFile > /dev/null 2>&1
  2. rm -fr /root/.oldFile > /dev/null 2>&1
  3. echo "welcome to Vi/Vim" > /root/oldFile && echo "welcome to Vi/Vim" > /root/.oldFile

具体编程要求如下:

使用vi/vim编辑器查看当前目录下已存在文件oldFile,然后保存退出vi/vim编辑器;

rm -fr /root/oldFile > /dev/null 2>&1

rm -fr /root/.oldFile > /dev/null 2>&1

echo "welcome to Vi/Vim" > /root/oldFile && echo "welcome to Vi/Vim" > /root/.oldFile

vim oldFile

然后再使用:wq退出,测评即可

 

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

编程要求

本关任务是学会如何使用vi/vim编辑器进行对文件编辑操作。

具体编程要求如下:

  1. 使用vi/vim编辑器在当前目录下打开一个新的文件newFile;
  2. 然后在文件中写入welcome to vi/vim字符串(注意不用输入换行操作);
  3. 保存并退出;

vim newFile 

首先进入的是命令模式,然后键盘按“i”进入输插模式,输入:

 welcome to vi/vim

键盘按 ESC退出插入模式,最后输入 

:wq

保存并退出,测评 

vi/vim命令模式

编程要求

本关任务是学会如何使用vi/vim编辑器在命令模式下对文件进行操作。

注意:在执行本关任务前,首先执行如下命令来初始化任务环境

  1. rm -fr /root/file.txt > /dev/null 2>&1
  2. echo "first" >> /root/file.txt
  3. echo "second" >> /root/file.txt
  4. echo "third" >> /root/file.txt
  5. echo "fourth" >> /root/file.txt
  6. echo "fifth" >> /root/file.txt

具体编程要求如下:

  1. 使用vi/vim编辑器打开当前目录下的file.txt文件;
  2. 删除当前文件第二行内容;
  3. 并将第一行内容复制到文件最后;
  4. 保存并退出;

rm -fr /root/file.txt > /dev/null 2>&1

echo "first" >> /root/file.txt

echo "second" >> /root/file.txt

echo "third" >> /root/file.txt

echo "fourth" >> /root/file.txt

echo "fifth" >> /root/file.txt

vim file.txt

然后将光标移到第二行,键盘按下dd,删除第二行 

 再将光标移回第一行,按下键盘yy复制第一行

 最后将光标移到最后一行,点击p粘贴

:wq 

测评

vi/vim底线命令模式 

编程要求

本关任务是学会在vi/vim底线命令模式下,将已打开文件的部分内容另存为一个文件,同时对当前文件中的本分内容进行替换操作。

注意:在执行本关任务前,首先执行如下命令来初始化任务环境

  1. rm -fr /root/oldFile.txt > /dev/null 2>&1
  2. echo "first old" >> /root/oldFile.txt
  3. echo "second old" >> /root/oldFile.txt
  4. echo "third old" >> /root/oldFile.txt
  5. echo "fourth old" >> /root/oldFile.txt
  6. echo "fifth old" >> /root/oldFile.txt

具体编程要求如下:

  1. 使用vi/vim编辑器打开当前目录下的oldFile.txt文件;
  2. 将文件第2-5行内容另存为oldFileCpy.txt文件;
  3. 将当前文件的所有old字符串替换为new字符串;
  4. 保存并退出;

rm -fr /root/oldFile.txt > /dev/null 2>&1

echo "first old" >> /root/oldFile.txt

echo "second old" >> /root/oldFile.txt

echo "third old" >> /root/oldFile.txt

echo "fourth old" >> /root/oldFile.txt

echo "fifth old" >> /root/oldFile.txt

vim oldFile.txt

 进入命令模式后输入

:2,5 w oldFileCpy.txt

 回车,此时文件已另存,接下来是字符串替换,输入

:1,$s/old/new/g

回车,最后使用:wq退出,测评 

读文件系统函数

read函数是系统调用从文件描述符fd指向的文件中,读取count个字节到buf中; 如果read成功,则返回读到的字节数,如果已达到结尾,则返回0,出错,返回-1 函数原型:

  1. //头文件
  2. #include <unistd.h>
  3. //原型
  4. ssize_t read(int fd, void *buf, size_t count);

参数说明:

  1. fd:文件描述符
  2. buf:保存读入信息的缓存
  3. count:要读取的字节数
#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");
    //请使用read函数将其读入buffer中

    n = read(fd, buffer, sizeof(buffer) - 1);

    
    buffer[n] = '\0';
    printf("%s\n", buffer);
    close(fd);
    return 0;
}

 

写文件系统函数

write函数

write系统调用将buf所指向的缓冲区的count个字节内容写入fd指向的文件; 如果write成功,则返回写入的字节数,出错返回-1 函数原型:

  1. //头文件
  2. #include <unistd.h>
  3. ssize_t write(int fd, const void *buf, size_t count);

参数说明:

  1. fd:要写入的文件
  2. buf:要写入的信息所在的缓存
  3. count:要写入的字节数
#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);
    }
    // 请使用read函数读取前1024字节的内容读到缓冲区buffer中
    while ((readbytes = read(resource_fd,buffer,FILESIZE))>0)
    {
        p = buffer;
        if ((readbytes == -1) && (errno != EINTR))
            break;
        else if (readbytes > 0)
        {
            // 请使用write函数读取到的前1024字节的内容写到目的文件中
            while ((writebytes = write(destination_fd,p,readbytes))>0)
            {
                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;
}

 

 进程基础操作

fork知识理解

fork函数后的的代码在子进程中也被执行,实际上其他代码也在子进程中,子进程执行位置为fork返回位置后,之前代码无法执行。

fork 理解步骤      

  step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。      

  step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。      

  step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。                    step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。      

这里有三个点非常关键:      

  1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)      

  2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。      

  3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。

编程要求

根据提示,在右侧编辑器编写代码,通过一行输出代码,使得子进程和父进程的都输出"bey!",之间用空格隔开。

#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{ 
    printf("bye! ");
  }

      return 0;
}

 

相关推荐

  1. os课程模拟考试(1~7)

    2024-06-16 19:48:02       7 阅读
  2. 数字媒体专业AR增强现实仿真模拟

    2024-06-16 19:48:02       22 阅读
  3. 排序问答

    2024-06-16 19:48:02       37 阅读
  4. BGP<span style='color:red;'>实</span><span style='color:red;'>训</span>

    BGP

    2024-06-16 19:48:02      14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-16 19:48:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-16 19:48:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-16 19:48:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-16 19:48:02       20 阅读

热门阅读

  1. redis大key优化

    2024-06-16 19:48:02       6 阅读
  2. 借报告Team ID错误谈谈Mac app文件签名与公证

    2024-06-16 19:48:02       7 阅读
  3. node环境常见问题

    2024-06-16 19:48:02       5 阅读
  4. 【杂记-浅谈SNMP网络管理标准协议】

    2024-06-16 19:48:02       10 阅读
  5. Azure OpenAI 服务

    2024-06-16 19:48:02       9 阅读
  6. LeetCode 0521.最长特殊序列 Ⅰ:脑筋急转弯

    2024-06-16 19:48:02       10 阅读
  7. Qt进程间通信QLocalSocket客户端无法接收消息

    2024-06-16 19:48:02       7 阅读
  8. Eclipse 内容辅助

    2024-06-16 19:48:02       10 阅读
  9. Redis数据结构之字符串(sds)

    2024-06-16 19:48:02       5 阅读
  10. c语言中的宏是什么?

    2024-06-16 19:48:02       7 阅读
  11. 速盾:服务器遭受ddos攻击如何防御

    2024-06-16 19:48:02       9 阅读
  12. 堆排序(Heap_sort)

    2024-06-16 19:48:02       9 阅读
  13. stm32实战

    2024-06-16 19:48:02       6 阅读