操作系统(openEuler)常见题型包含选择填空操作组合各类题型(包含题目解析)期末复习首选包含理论与实操,掌握这些,考试稳过!

一、选择题

1、在安装openEuler操作系统时,( )分区强制为主分区

  • ​ A./boot

    开机:boot

  • ​ B./swap

  • ​ C./home

  • ​ D./etc

2、安装openEuler操作系统时,设置引导装载程序的安装位置,默认安装在( )的MBR上

  • ​ A./dev/hda

  • B./dev/sda

    表示第一块硬盘

  • C./dev/hdb

  • D./dev/sdb

3、Linux有两种常用的引导装载程序:LILO和( )

  • A.MBR
  • B.GPT
  • C.SCSI
  • D.GRUB

4、以下哪个系统操作界面安装选项没有图形界面和网络管理功能。

  • A. Desktop
  • B. Minimal
  • C. Basic Server
  • D. Minimal Desktop

5、从图形化界面切换到命令行界面的快捷键是:

  • A. Ctrl+Alt+F7
  • B. Ctrl+Alt+F2
  • C. win+R
  • D. win+L

6、为了更好的保护系统的安全,建议用户定期使用( )命令来修改系统中相关用户的口令

  • A. passwd
  • B. password
  • C. change
  • D. key

7、( )用户可以修改任意用户的口令。

  • A.administrator
  • B. root
  • C.user
  • D.special user

8、openEuler的登陆界面有两种:( )界面和图形化界面

  • A.桌面化
  • B.命令行
  • C.操作行
  • D.管理化

9、若要安装图形化操作界面,安装时的选项应该是:

  • A. Basic Server
  • B. Minima
  • C. Desktop

10、下列变量名中有效的shell变量名是( )。

  • A.-2-time
  • B.2$3
  • C.trust_no_1
  • D.2004file

11、下面哪个文件包含bash默认的环境变量( )

  • A.~/.profile

    用户环境变量

  • B./bash

  • C./etc/profile

    默认环境变量

  • D.~/bash

12、当字符串用单引号’ ’括起来时,SHELL将( )。

  • A.解释引号内的特殊字符

  • B.执行引号中的命令

  • C.不解释引号内的特殊字符

    字符串原样输出

  • D.结束进程

13、一个bash shell脚本的第一行是( )。

  • A.!#/bin/bash
  • B. #/bin/bash
  • C. /bin/bash
  • D. #!/bin/bash

14、下面哪个命令是用来定义shell的全局变量( )

  • A. Exportfs
  • B. alias
  • C.exports
  • D.export

15、系统配置文件,一般来说大部分位于( )目录下。

  • A. /boot

  • B./etc

    etcetera:系统配置信息存放目录

  • C./home

  • D./usr

16、若当前目录为/home,命令ls -l将显示home目录下的( )。

  • A.所有文件
  • B.所有隐含文件
  • C.所有非隐含文件
  • D.文件的具体信息

17、你使用命令 "vi /etc/inittab”查看该文件的内容,你不小心改动了一些内容,为了防止系统出问题,你不想保存所修改内容,你应该如何操作( )

  • A.在未行模式下,键入:wq

  • B.在末行模式下,键入:q!

    对于已经修改过的文件要加上 ! 表示强制退出

  • C.在末行模式下,键入:x!

  • D.在编辑模式下,键入“ESC”键直接退出vi

18、如果您想列出当前目录以及子目录下所有扩展名为“.txt”的文件,那么您可以使用的命令是

  • A. ls *.txt

    * :通配符

  • B.find -name “.txt”

  • C.ls -d .txt

  • D. find . “.txt”

19、用ls -al 命令列出下面的文件列表,( )文件是符号连接文件

  • A.-rw-rw-rw-2 hel users 56 sep 09 11:05 hello

  • B.-rwxrwxrwx 2 hel users 56 Sep09 11:05 goodbey

  • C.drwxr–r–1 hel users 1024 Sep 10 08:10 zhang

  • D.lrwxr–r–1 hel users 2024 sep 12 08:12 cheng

    -:表示目录 d : 表示文件 l:表示链接(LINK)

20、Linux三种特殊权限中仅用于目录文件的权限是( )

  • A.SUID
  • B.SGID
  • C.黏滞位SBIT
  • D.都可以

21、若要将当前目录中的myfile.txt文件压缩成myfile.txt.tar.gz,则实现的命令为

  • A.tar -cvf myfile.txt myfile.txt.tar.gz
  • B.tar -zcvf myfile.txt myfile.txt.tar.gz
  • C.tar -zcvf myfile.txt.tar.gz myfile.txt
  • D.tar -cvf myfile.txt.tar.gz myfile.txt

22、下列哪个命令在建立一个 tar归档文件的时候列出详细列表( )。

  • A. tar -t
  • B.tar -cv
  • C.tar -cvf
  • D.tar -r

23、可以用来对文件xxx.gz解压缩的命令是( )。

  • A.compress
  • B.uncompress
  • C.gunzip
  • D. tar

24、对文件进行归档的命令为( )

  • A. Gzip
  • B. tar
  • C. dump
  • D. dd

25、若要对myfile.txt.tar.gz包进行解压还原,则应使用命令( )来实现。

  • A.tar -xvf myfile.txt.tar.gz
  • B.tar -cvf myfile.txt.tar.gz
  • C.tar -zcvf myfile.txt.tar.gz
  • D.tar -zxvf myfile.txt.tar.gz

26、以下哪项不属于单处理机系统中多道程序运行时的特点?

  • A.多道程序被同时存放在内存中
  • B.宏观上并行执行
  • C.微观上并行执行
  • D.微观上串行执行

27、以下哪个操作系统不属于分时操作系统?

  • A. RedHat
  • B. Windows
  • C.VxWorks
  • D.Android

28、操作系统是一组____

  • A.文件管理程序
  • B.资源管理程序
  • C.中断处理程序
  • D.设备管理程序

29、以下哪项不是操作系统关心的主要问题?

  • A.管理计算机裸机
  • B.设计、提供用户程序与计算机硬件系统的界面
  • C.管理计算机系统资源
  • D.高级程序设计语言的编译器

30、下列关于操作系统的叙述正确的是?

  • A.操作系统是硬件和软件之间的接口
  • B.操作系统是主机与外设之间的接口
  • C.操作系统是用户与计算机之间的接口
  • D.操作系统是源程序与目标程序之间的接口

31、在Linux系统中,根用户登录后,其当前目录为__,普通用户wang登录后,一般情况下,其当前目录为

  • A./home; /root;
  • B./root; /home/wang;
  • C./root; /etc;
  • D./etc;/home/wang;

32、除了易用性、高效性、可靠性和可扩展性这四个设计目标,现代操作系统还应考虑能效性。以下哪于操作系统改善计算机能耗的途径?

  • A.根据工作负载调整CPU频率
  • B.采用模块化的结构设计
  • C.采用动态电压和频率缩放技术
  • D.休眠或关闭部分空闲设备(如磁盘)

33、哪个目录存放用户密码信息( )

  • A. /boot

  • B./etc

    etcetera:系统配置信息存放目录

  • C. /var

  • D. /dev

34、openEuler一般被用作哪一类操作系统?

  • A.个人计算机操作系统
  • B.智能移动终端操作系统
  • C.轻量级嵌入式操作系统
  • D.服务器操作系统

35、默认情况下管理员创建了一个用户,就会在( )目录下创建一个用户主目录。

  • A./usr
  • B./home
  • C./root
  • D./etc

36、__目录用来存放系统管理员使用的管理程序。

  • A. /sbin;

    superBin

  • B./bin;

  • C. /root;

  • D. /home;

37、以下哪一种指令显示的结果为$openEuler?

  • A.\echo $openEuler
  • B.echo “$openEuler”
  • C.echo ‘$openEuler’
  • D.echo “${openEuler}”

38、若要结束进程,应使用( )命令。

  • A. kill
  • B.ps
  • C. pss
  • D. pstree

39、一个Bash Shell脚本的第1行是什么?

  • A. #!/bin/bash
  • B. #/bin/bash
  • C.#/bin/csh
  • D. /bin/bash

40、哪个符号加在命令后面可以在后台执行程序(选择最合适的答案)

  • A. @
  • B.&
  • C.#
  • D.*

41、以下哪个命令可以将普通用户转换成超级用户?

  • A.super
  • B. passwd
  • C. tar
  • D.su

42、终止一个前台进程可能用到的命令和操作是( )

  • A. Kill

  • B.+C

    此处应为 CTRL+C 代表强制结束当前前台进程

  • C.shut down

  • D. halt

43、在一行内运行多个命令需要用什么字符隔开?

  • A. @
  • B. $
  • C.;
  • D.*

44、下面哪一个选项不是Linux系统的进程类型:( )

  • A.交互进程
  • B.批处理进程
  • C.守护进程
  • D.就绪进程

45、哪个命令显示当前系统运行的进程列表?( )

  • A. ps -ax
  • B.proc -a
  • C. stat
  • D. ls

46、在终端中执行echo"current path:" ‘pwd’ ",结果是?

  • A. path:‘/home/openEuler’
  • B.current
  • C.current path:‘pwd’
  • D.current path: pwd

47、临界区是指并发进程中涉及共享变量的( )

  • A.程序段
  • B.管理信息区
  • C.公共数据区
  • D.信息存储区

48、下列有关fork( )函数返回值说法错误的是( )

  • A.函数成功返回时,一次返回两个值,错误返回时为-1

  • B.返回值等于0表示子进程

  • C.返回值大于0表示父进程

  • D.大于0返回值为父进程的PID号

    大于0返回值为子进程PID号

49、LINUX交换分区的格式为( )。

  • A.ext2

  • B.ext3

  • C.FAT

  • D.swap

    swsp:交换

50、下面程序的输出是什么( )

#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
	if(fork() == 0)
        printf("hello");
	else
		printf("world");
return 0;
  • A.helloworld
  • B. wordhello
  • C. Hello
  • D.不确定

51、以下对磁盘文件管理的描述,不正确的是( )。

  • A.在Linux图形化桌面环境中,使用文件浏览管理器来实现对磁盘或文件的管理。
  • B.对磁盘或文件的管理,很多情况下均可使用快捷菜单来实现对其操作。
  • C.文件浏览管理器提供有文件搜索功能。
  • D.文件浏览管理器中,无法实现对U盘的格式化操作。

52、下面说法不正确的是( )

  • A.管道和命名管道是最早进程间通信机制之一

  • B.消息队列是将消息按队列的方式组织成的链表,每个消息都是其中的一个节点

  • C.进程创建一般由create函数完成

    进程创建使用Fork()函数

  • D.共享内存和消息都是由Linux内核来管理和分配资源

53、光盘所使用的文件系统类型为( )

  • A. ext2
  • B. ext3
  • C.swap
  • D.ISO 9660

54、关于SIGCHLD信号说法错误的是( )

  • A.在子进程退出时,会向父进程发送该信号
  • B.需要及时处理SIGCHLD防止僵尸进程
  • C.SIGCHLD信号的默认处理方式是忽略
  • D.由于SIGCHLD信号默认方式是忽略,所以在代码中不需要手动设置SIGCHLD信息的处理方式,也不会产生僵尸进程

55、下列哪种通信方式只能用于具有亲缘关系进程之间的通信( )

  • A.匿名管道
  • B.消息队列
  • C.共享内存
  • D.命名管道

56、显示已经挂装的文件系统磁盘inode使用状况的命令是( )?

  • A. df -i
  • B. su -I
  • C. du -I
  • D.free -i

57、线程使用以下哪种方式退出时,无法保证不结束整个进程?

  • A.从启动例程中返回

  • B.线程执行exec函数后,导致当前进程地址空间全部更新

    地址更新导致失去PCB

  • C.调用pthread_exit

  • D.被统一进程的其他线程取消

58、以下说法正确的是( )。

  • A.只有用户级线程的操作系统中,调度以线程为单位,由操作系统控制进程中的多个线程运行。

  • B.只有用户级线程的操作系统中,调度以进程为单位,由操作系统控制进程中的多个线程运行。

  • C.只有用户级线程的操作系统中,调度以进程为单位,由用户程序控制进程中的多个线程运行。

    用户级线程,线程由用户代码实现,操作系统看不到进程

  • D.只有用户级线程的操作系统中,调度以线程为单位,由用户程序控制进程中的多个线程运行。

59、调用pthread_create函数创建一个线程后,( )会先运行。

  • A.该进程的主线程

  • B.调用pthread_create函数的线程

  • C.创建的新线程或调用pthread_create函数的线程

    分时操作系统程序异步执行

  • D.创建的新线程

60、假设U盘的设备名为/dev/sdb,现要将U盘格式化为FAT分区,以下命令中不能实现的是( )

  • A. mkfs.vfat /dev/sdb

    该命令为格式化FAT格式系统应为正确选项

  • B.mkfs.msdos /dev/sdb

  • C.mkdos /dev/sdb

    无效命令

  • D.mkfs.ext3 /dev/sdb

    该命令为格式化EXT3格式系统应为不能实现选项

😥此题暂时保留,已反馈老师,无回应则照题库作答

61、一个MBR硬盘最多能够被分成___个主分区。

  • A.1
  • B.2
  • C.3
  • D.4

62、以下对于vi编辑器用法的描述,不正确的是( )。

  • A.插入模式下,按ESC键,可进入命令模式

  • B.在命令模式下,输入3dd,可立即删除从当前光标所在行开始的后面连续3行的内容

  • C.当用户对内容做了一些编辑修改后,若要放弃修改退出,则按Esc键返回命令模式,然后输入:q并回车退出

    对于已经修改过的文件要加上 ! 表示强制退出

  • D.在命令模式按i键,可进入插入(编辑修改)模式

63、以下关于线程清理函数的说法,错误的是( )。

  • A.线程从其代码中的return语句结束时,会引发pthread_cleanup_push和pthread_cleanup_pop函数执行
  • B.pthread_cleanup_push和pthread_cleanup_pop函数都是以宏的形式实现的
  • C.线程从其代码中的pthread_exit函数结束时,会引发pthread_cleanup_push和pthread cleanup_pop函数执行
  • D.pthread_cleanup_push和pthread_cleanup_pop函数必须成对使用

64、在vi编辑器中的命令模式下,撤销上一次操作,可使用( )命令。

  • A.上箭头
  • B.下箭头
  • C.backspace
  • D.u

65、以下不属于线程同步机制的是( )。

  • A.正则表达式
  • B.互斥锁
  • C.读写锁
  • D.条件变量

66、以下关于互斥锁的描述,错误的是( )。

  • A.若线程申请的互斥锁正被其他线程占用,则该线程将被挂起

    阻塞是低级调度,挂起是中级调度

  • B.互斥锁的操作具有原子性

  • C.互斥锁可以用来锁定资源或进程

    进程不可以被锁定

  • D.互斥锁也是一种信号量

67、以下函数中,( )是用于互斥锁上锁的。

  • A. pthread_cond_signal
  • B.pthread_rwlock_rdlock
  • C. Pthread_mutex_lock
  • D. pthread_spin_init

68、在openeuler系统中,下列哪个命令可以用来建立分区:

  • A. fdisk
  • B. mkfs
  • C.tune2fs
  • D.mount

69、以下( )步骤是正确的。

①对互斥量加锁

②改变互斥量保护的条件

③给等待条件的线程发信号

④对互斥量解锁

  • A.①②③④
  • B.①②④③
  • C.②③①④
  • D.③④①②

70、在openeuler系统中,下列哪个命令可以用来将分区挂载到目录:( )

  • A. fdisk
  • B. mkfs
  • C.tune2fs
  • D.mount

71、比较文件的差异要用到的命令是以下哪一种?

  • A. diff

    差异:difference

  • B. cat

  • C. wc

  • D.head

72、将某分区(hda1)挂载到Linux文件系统的/winsys目录下,命令是( )。

  • A. mount dev/hda1 /winsys

  • B. mount /dev/hda1 /winsys

    /:代表根目录 没有斜杠代表当前目录

  • C.mount /dev/hda1 winsys

  • D.mount dev/hda1 winsys

73、存放设备文件的相关文件目录是?

  • A. /dev

    设备:device

  • B./etc

  • C./lib

  • D./bin

74、rm命令表示什么?

  • A.文件复制命令

  • B.移动文件命令

  • C.文件内容统计命令

  • D.文件删除命令

    删除:remove

75、在openEuler系统中,用户文件描述符0表示?

  • A.标准输出设备文件描述符 1
  • B.标准输入设备文件描述符 0
  • C.管道文件描述符 |
  • D.标准错误输出设备文件描述符 2

76、在使用mkdir命令创建新的目录时,在其父目录不存在时先创建父目录的选项是?

  • A. -d

  • B. -m

  • C. -P

    parents:父

  • D. -f

77、执行命令“chmod o+rw myfile”后,myfile文件的权限变化为?

  • A.所有用户都可读写myfile文件
  • B.其他用户可读写myfile文件
  • C.同组用户可读写myfile文件
  • D.文件所有者读写myfile文件

78、以下不是用来分配内存的函数的是?

  • A. realloc()

  • B. malloc()

  • C.free()

    释放内存

  • D. calloc()

79、lseek()中第三个参数的值为0表示?

  • A.文件读写指针当前位置
  • B.文件开始位置
  • C.文件结束位置
  • D.都不是

lseek()函数的三个参数含义如下:

  1. 文件描述符:这是第一个参数,用于指定要操作的文件。在Unix/Linux系统中,每个打开的文件都有一个唯一的文件描述符,它是一个非负整数。
  2. 偏移量:这是第二个参数,表示需要移动到的新位置相对于第三个参数指定的参照点的偏移量。偏移量可以是正数(向后移动)或负数(向前移动)。
  3. 参照点:这是第三个参数,用于指定偏移量的起始点。它有三个可能的值:
    • SEEK_SET:从文件开始处计算偏移量。如果偏移量为0,则指向文件的起始位置。
    • SEEK_CUR:从当前文件指针位置计算偏移量。如果之前没有使用过lseek(),效果与SEEK_SET相同。
    • SEEK_END:从文件末尾计算偏移量。如果偏移量为0,则指向文件的末尾
    • 0:开始

80、下面更改文件命令只能更改符号连接的目标文件的权限的命令是?

  • A.chgrp
  • B.chown
  • C.chmod
  • D.以上都不对

81、下面关于ftell()函数成功调用说法不正确的是?

  • A.返回读写指针当前相对文件起始位置的位移量
  • B.返回读写指针当前相对文件结束位置的位移量
  • C.会清除流结束标志
  • D.会撤销已调用ungetc()对流的影响

82、在linux系统中,重新启动可使用( )命令。

  • A.ctrl+alt+del
  • B. halt
  • C.shutdown -h
  • D. reboot

83、以下函数中表示从某流中读取一个字符但该函数不带参数,表示从标准输入流中读字符的函数是?

  • A. Getc
  • B. gets
  • C.fgec
  • D. getchar

84、在函数fopen()中文件打开模式中不是可读写的方式打开文件模式是?

  • A.r
  • B.r+
  • C.a+
  • D.w+

85、格式化输出可把格式化数据输出到标准输出、指定文件及字符缓冲区。其中( )函数是将格式化数据输出到指定大小的字符缓冲区?

  • A.sprintf

    这个函数用于将格式化的数据写入一个字符串缓冲区。然而,它不会检查目标缓冲区的大小,因此如果提供的缓冲区太小,可能会导致缓冲区溢出,从而引发安全问题

  • B.snprintf

    与sprintf类似,但snprintf允许指定最大写入的字符数(包括终止的空字符)。这有助于防止缓冲区溢出,提高代码的安全性

  • C. fprintf

    这个函数用于将格式化的数据输出到指定的文件流中。它通常用于将数据写入文件或标准输出(如stdout)

  • D. printf

    这个函数用于将格式化的数据输出到标准输出(通常是屏幕)。它常用于调试和显示程序运行结果

86、.以下选项中,哪个命令可以关机?

  • A. init 0

    关机

  • B. init 1

    单用户模式

  • C. init 5

    多用户模式

  • D. init 6

    重启

87、以下选项中,哪个命令可以重启?( )

  • A. init 0
  • B.init 1
  • C.init 5
  • D.init 6

88、字符界面下使用shutdown命令重启计算机时所用的参数是( )

  • A. -h
  • B.-t
  • C.-k
  • D.-r

89、使用vi编辑器时,命令"dd"用来删除当前的( )

  • A.行
  • B.变量
  • C.字
  • D.字符

90、vi中哪条命令是不保存强制退出( )

  • A.:wq
  • B.:wq!
  • C.:q!
  • D.:quit

二、多选题

1、操作系统的安装有多种方式:

  • A.光盘安装

  • B.软盘安装

    太小了装不下

  • C.U盘安装

2、在手工操作时期,用户可以使用哪些介质将程序或数据输入计算机?

  • A.光盘
  • B.纸带
  • C.卡片
  • D.U盘

3、在批处理系统时代(晶体管时代),批处理方式有哪些?

  • A.联机批处理
  • B.多道批处理
  • C.脱机批处理
  • D.并行批处理

4、实时操作系统的主要特点包括?

  • A.多路性
  • B.独占性
  • C.及时响应
  • D.高可靠性

5、内存管理的主要任务有?

  • A.物理内存的分配和回收
  • B.虚拟地址到物理地址的映射
  • C.地址转换的加速
  • D.突破物理内存限制

6、openEuler的优势体现在?

  • A.多核调度技术
  • B.软硬件协同
  • C.轻量级虚拟化
  • D.指令级优化
  • E.智能化引擎

三、操作题

1、信号量IPC操作考查

#include <errno.h>
 #define MAX_SEMAPHORES  5
#include <stdio.h>
 #include <sys/types.h>
 #include <sys/sem.h>
 #include <errno.h>
 #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++ )
        {
            /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
            printf("Semaphore %d, value %d\n", i, sem_read_array[i] );
        }
        ret = semctl( semid, 0, IPC_RMID );
    }
    else
        printf("Could not allocate semaphore (%d)\n", errno);
    return 0;
}

2、消息队列IPC操作考察

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<string.h>
#include<sys/msg.h>
#define BUFSIZE 128
struct msg_buf
{
	long type;
	char msg[BUFSIZE];
};

int main(int argc,char *argv[])
{
	key_t key;
	int msgid;
	struct msg_buf msg_snd,msg_rcv;
	struct msginfo buf;
	char *ptr="helloOpenEuler";
	memset(&msg_snd,'\0',sizeof(struct msg_buf));
	memset(&msg_rcv,'\0',sizeof(struct msg_buf));
	msg_rcv.type=1;
	msg_snd.type=1;
	memcpy(msg_snd.msg,ptr,strlen(ptr));
	if((key=ftok(".",'A'))==-1)
	{
		perror("ftok");
		exit(EXIT_FAILURE);
	}
	if((msgid=msgget(key,0600|IPC_CREAT))==-1)
	{
		perror("msgget");
		exit(EXIT_FAILURE);
	}
	printf("msgsnd_return=%d\n",msgsnd(msgid,(void *)&msg_snd,strlen(msg_snd.msg),0));	
	msgctl(msgid,MSG_INFO,&buf);
/*请分别输出buf.msgmax=  buf.mnb=  buf.msgpool=  buf.msgmap=  buf.msgmni=  buf.msgssz=  buf.msgtql=  buf.msgseg= 每个之间换行隔开*/
printf("buf.msgmax=%d\nbuf.msgmnb=%d\nbuf.msgpool=%d\nbuf.semmap=%d\nbuf.msgmni=%d\nbuf.msgssz=%d\nbuf.msgtql=%d\nbuf.msgseg=%d\n",buf.msgmax,
    buf.msgmnb,buf.msgpool,buf.msgmap,buf.msgmni,buf.msgssz,buf.msgtql,buf.msgseg);

	printf("msgrcv_return=%d\n",msgrcv(msgid,(void *)&msg_rcv,BUFSIZE,msg_rcv.type,0));
/*输出msg_rcv.msg= 即收到的消息*/
    printf("msg_rcv.msg=%s\n",msg_rcv.msg);
	printf("msgctl_return=%d\n",msgctl(msgid,IPC_RMID,0));
}

3、文件的读写

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

#define BUFFER_SIZE 1024
//请不要更改文件路径!!!
#define SRC_FILE_NAME "/data/workspace/myshixun/fileSystem/src/fileProgram/src_file"
//请不要更改文件路径!!!
#define DEST_FILE_NAME "dest_file"
#define OFFSET 10240

int main()
{
	int src_file,dest_file;
	unsigned char buff[BUFFER_SIZE];
	int real_read_len;

    //请在此处填入代码,使用合适的模式打开源目标SRC_FILE_NAME文件
	src_file = open(SRC_FILE_NAME,O_RDONLY);
    //请在此处填入代码,使用合适的模式打开写入文件目标DEST_FILE_NAME文件,需要考虑到文件是否存在?
	dest_file = open(DEST_FILE_NAME, O_WRONLY | O_CREAT);
    //dest_file = open(DEST_FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC);
	if(src_file < 0 || dest_file < 0)
	{
		printf("Open file error!\n");
		exit(1);
	}

    //请在此处填入代码,设置偏移量读取文件最后10KB数据

    lseek(src_file,-OFFSET,SEEK_END);
	while((real_read_len =  read(src_file,buff,sizeof(buff))) > 0)
	{
        //请在此处填入代码,使用buff写入目标文件
		write(dest_file,buff,real_read_len);
	}
	close(dest_file);
	close(src_file);

	return 0;
}

4、读文件系统函数

#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;
}

5、openEuler初体验

第一关

#!/bin/bash

#在以下部分写出完成任务的命令
#*********begin*********#
cd /
ls -a
#********* end *********#

第二关

#!/bin/bash

#在以下部分写出完成任务的命令
#*********begin*********#
rm -rf newfile
touch newfile
mkdir newdir
mv newfile newdir/newfileCpy
#********* end *********#

第三关

#!/bin/bash

#在以下部分写出完成任务的命令
#*********begin*********#
man 3 fopen 
#********* end *********#

6、openEuler 文件/目录管理

openEuler之文件创建/删除

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
touch file1 file2
rm -rf oldFile1 oldFile2
#************end**************#

openEuler之目录创建/删除

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
mkdir newDir1 newDir2
rm -rf oldDir1 oldDir2
#************end**************#

openEuler之文件复制/重命名

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
cp file1 ./Dir
cp file2 ./Dir
cp file1 ./Dir/file1Cpy
mv file3 ./Dir
mv file4 ./Dir
mv file5 file6
#************end**************#

openEuler之目录复制/重命令

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
cp -r Dir1 ./Dir
cp -r Dir2 ./Dir
cp -r Dir1 ./Dir/Dir1Cpy
mv Dir3 ./Dir
mv Dir4 ./Dir
mv Dir5 Dir6
#************end**************#

openEuler之文件/目录内容查看

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
cat file1
head -5 file2
tail -5 file2
ls -a /home
#************end**************#

7、openeuler 文件/目录高级管理一

openEuler文件权限修改

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
chmod u=x oldFile1
chmod g-w oldFile2
chmod o+x oldFile3
chmod u=r,g=w,o=x oldFile4
#************end**************#

openEuler目录权限修改

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
chmod u=x oldDir1
chmod g-w oldDir2
chmod o+x oldDir3
chmod u=r,g=w,o=x oldDir4
chmod -R u=r,g=w,o=x oldDir5
#************end**************#

openEuler修改文件/目录所有者

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
chown oldUser oldFile
chown oldUser oldDir1
chown -R oldUser oldDir2
#************end**************#

openEuler文件/目录所属组修改

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
chgrp oldGroup oldFile
chgrp oldGroup oldDir1
chgrp -R oldGroup oldDir2
#************end**************#

8、openEuler之文件/目录搜索

查询命令-which/whereis

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
which useradd
whereis useradd
whereis -m useradd
#************end**************#

查询命令-find

find . -name "*.conf"
find . -name "my*"
find /root -size +1M
find /root -name "*.Link" -a -type l

9、openEuler之用户管理

创建/删除新用户

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
sudo useradd -m newUser
sudo userdel -r oldUser
cd /home/newUser
pwd
#************end**************#

openEuler 用户密码管理

#!/bin/bash

#创建newUser新用户
#***********begin*************#
useradd newUser
#************end**************#

#在符号<<前输入设置用户密码的命令(命令与<< EOF保持在同一行), 密码输入在下一行,确认密码输入在下下行
#例如:
#command << EOF
#password
#password
#EOF
#***********begin*************#
passwd newUser << EOF
123456
123456
EOF
#************end**************#

openEuler用户权限切换

#!/bin/bash

#创建newUser新用户
#***********begin*************#
useradd newUser
#************end**************#

#在符号<<前输入设置用户密码的命令(命令与<< EOF保持在同一行), 密码输入在下一行,确认密码输入在下下行
#例如:
#command << EOF
#password
#password
#EOF
#***********begin*************#
passwd newUser << EOF
123456
123456
EOF
#************end**************#

#使用su命令切换当前用户身份为newUser,并且执行whoami指令,然后恢复原来的身份;
#提示使用su命令的-c参数完成
#***********begin*************#
su  newUser -c whoami
#************end**************#

10、openEuler之用户高级管理

创建/删除用户组

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
groupadd newGroup
groupadd -g 1010 newGroupID
groupdel oldGroup
#************end**************#

openEuler用户所属组变更

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
useradd newUser
usermod -a -G oldGroup newUser
#************end**************#

openEuler用户/用户组编辑

#!/bin/bash

#在以下部分写出完成任务的命令
#***********begin*************#
usermod -l newName oldName
usermod -d /home/newName newName
groupmod -n newGroup oldGroup
#************end**************#

11、查看进程

#!/bin/bash

#在以下部分写出完成任务的命令
#*********begin*********#
ps -aux
ps -aux|grep php
ps -u root
pstree
#********* end *********#

12、创建进程

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
void main()
{
  int p1,i;
  while((p1=fork())==-1;
  if (p1>0)
     for (i=0;i<5;i++)
  {
     printf("I am parent.\n");
     sleep(1);
  }
else
  for(i=0;i<5;i++)
  {
    printf("I am child.\n");
    sleep(1);
   }
}

13、进程同步原理

1、P、V 操作中,P 操作的作用是? ABB ACA
    A、请求资源并可能阻塞 √
    B、释放资源并唤醒进程
    C、检查信号量值并打印
    D、初始化信号量

2、信号量的值小于 0 时,表示什么?
    A、当前可用资源的数量
    B、等待使用该资源的进程个数(绝对值)√
    C、没有进程在等待资源
    D、信号量被错误设置

3、在信号量机制中,当信号量的值为 -3 时,表示什么?
    A、有 3 个资源可用
    B、有 3 个进程正在等待资源 √
    C、进程处于阻塞状态
    D、进程处于就绪状态

4、在 openEuler 中,semget 函数用于?
    A、创建或访问一个信号量集 √
    B、对信号量执行 P 或 V 操作
    C、阻塞父进程,子进程执行
    D、获取与路径相对应的键值

5、以下哪个函数用于唤醒等待信号量的进程?
    A、semop
    B、semctl
    C、wakeup(在 P、V 操作实现中) √
    D、ftok

6、在进程同步原语中,wait() 函数的作用是?
    A、阻塞父进程,子进程执行 √
    B、创建或访问信号量集
    C、对信号量执行 P 操作
    D、获取与路径相对应的键值

14、进程通信

信号与管道

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0
#define SIZE 11
typedef int QueueData; //定义一个整型变量 QueueData,与为基本数据类型定义新的别名一样

//任务:定义队列结构体
/*********begin***********/
typedef struct _queue{
   int data[SIZE];
   int front;
   int rear;
}Queue;
/**********end************/

//任务:信号量结构体
/*********begin***********/
struct data{
   sem_t count;
   Queue q;
};
struct data sem;
/**********end************/
pthread_mutex_t mutex; //互斥变量使用特定的数据类型
int num = 0;

int InitQueue(Queue *q) { 
    //任务:队列初始化
    /*********begin***********/
   if(q==NULL){
      return FALSE;
   }
   q->front=0;
   q->rear=0;
   return TRUE;
    /**********end************/
}

int QueueEmpty(Queue *q) { 
    //任务:判断空队情况
    /*********begin***********/
   if(q==NULL){
      return FALSE;
   }
   return q->front==q->rear;
    /**********end************/
}

int QueueFull(Queue *q) {   
    //任务:判断队满的情况
    /*********begin***********/
   if(q==NULL){
      return FALSE;
   }
   return q->front==(q->rear+1)%SIZE;
    /**********end************/
}

int DeQueue(Queue *q, int &x) { 
    //任务:出队函数
    /*********begin***********/
   if(q==NULL){
      return FALSE;
   }
   if(QueueEmpty(q)){
      return FALSE;
   }
   q->front=(q->front+1)%SIZE;
   x=q->data[q->front];
   return TRUE;
    /**********end************/
}

int EnQueue(Queue *q, int x) { 
    //任务:进队函数
    /*********begin***********/
   if(q==NULL){
      return FALSE;
   }
   if(QueueFull(q)){
      return FALSE;
   }
   q->rear=(q->rear+1)%SIZE;
   q->data[q->rear]=x;
   return TRUE;
    /**********end************/
}

void* Producer(void* arg) {
    //任务:设置生产者线程
    /*********begin***********/
   int i=0;
   while(i<10){
      i++;
      int time=rand()%10+1;
      usleep(time*100000);
      sem_wait(&sem.count);
      pthread_mutex_lock(&mutex);
      if(!QueueFull(&sem.q)){
         num++;
         EnQueue(&sem.q,num);
         printf("produce a message, count=%d\n",num);
      }
      else printf("Full\n");
      pthread_mutex_unlock(&mutex);
      sem_post(&sem.count);
   }
   printf("i(producer)=%d\n",i);
    /**********end************/
}

void* Customer(void* arg) {
    //任务:设置消费者线程
    /*********begin***********/
    int i=0;
   while(i<10){
      i++;
      int time=rand()%10+1;
      usleep(time*100000);
      sem_wait(&sem.count);
      pthread_mutex_lock(&mutex);
      if(!QueueEmpty(&sem.q)){
         num--;
         DeQueue(&sem.q,num);
         printf("consume a message, count=%d\n",num);
      }
      else printf("Empty\n");
      pthread_mutex_unlock(&mutex);
      sem_post(&sem.count);
   }
   printf("i(customer)=%d\n",i);

    /**********end************/
}

int main() {
    //任务:完善主函数
    /*********begin***********/
   srand((unsigned int)time(NULL));
   sem_init(&sem.count,0,10);
   pthread_mutex_init(&mutex,NULL);
   InitQueue(&(sem.q));
   pthread_t producid;
   pthread_t consumid;
   pthread_create(&producid,NULL,Producer,NULL);
   pthread_create(&consumid,NULL,Customer,NULL);
   pthread_join(consumid,NULL);
   sem_destroy(&sem.count);
   pthread_mutex_destroy(&mutex);
   return 0;
    /**********end************/
}

涉及的系统调用

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

int main() {
    int pipefd[2];
    pid_t p1, p2;
    char buffer[1024];
    ssize_t bytesRead;
    // 创建管道
    if (pipe(pipefd) == -1) {
        perror("pipe");
        return 1;
    }

    // 创建第一个子进程 p1
    p1 = fork();
    if (p1 < 0) {
        perror("fork");
        return 1;
    } else if (p1 == 0) { // 子进程 p1
        close(pipefd[0]); // 关闭读端
        const char *msg = "child1 process is sending message!\n\n";
        write(pipefd[1], msg, strlen(msg));
        close(pipefd[1]); // 关闭写端
        return 0;
    }

    // 创建第二个子进程 p2
    p2 = fork();
    if (p2 < 0) {
        perror("fork");
        return 1;
    } else if (p2 == 0) { // 子进程 p2
        close(pipefd[0]); // 关闭读端
        const char *msg = "child2 process is sending message!\n\n";
        write(pipefd[1], msg, strlen(msg));
        close(pipefd[1]); // 关闭写端
        return 0;
    }

    // 父进程
    close(pipefd[1]); // 关闭写端
    while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer) - 1)) > 0) {
        buffer[bytesRead] = '\0'; // 确保字符串以 null 结尾
        printf("%s", buffer);
    }
    close(pipefd[0]); // 关闭读端

    // 等待子进程结束
    waitpid(p1, NULL, 0);
    waitpid(p2, NULL, 0);

    return 0;
}

15、条件判断与循环结构

if语句

if [ $current_pod_num -gt 140 ]
then
   echo "pod数量为$current_pod_num,自动增加三台k8s集群节点"
elif [ $current_pod_num -ge 90 ]
then
    echo "pod数量为$current_pod_num,自动增加一台k8s集群节点"
else
   echo "pod数量为$current_pod_num,不需要增加k8s集群节点"
fi

case语句

1、已经脚本/home/a.sh的内容如下:

    name=$1
    case $name in 
    www.baidu)
        echo "三级域名"
    educoder.net)
        echo "二级域名"
    net)
        echo "主机名"
    esac
在终端执行bash /home/a.sh "www.baidu",以下说法正确的是:
A、屏幕输出内容为"三级域名”。
B、屏幕输出内容为"二级域名”。
C、屏幕输出内容为"主机名”。
D、屏幕输出错误,异常。 √

2、已知道/opt/a.sh的脚本内容如下:
    #!/bin/bash
    name=$1  
    case $name in
        [0-9a-zA-Z])
            echo "字母或者数字"
            ;;
        [0-9])
            echo "数字"
            ;;

        0|4)
            echo "0或者4"
            ;;
        *)
            echo "路过"
            ;;
    esac
在终端执行bash /home/a.sh 4,下面说法正确的是:
A、输出结果为“0或者4”,因为输入的数字4,正则优先匹配到 0|4这个条件。
B、输出结果为“数字”, 因为输入的数字4,正则优先匹配到[0-9]的条件。
C、输出结果为“字母或者数字”,因为输入的数字4,正则优先匹配到[0-9a-zA-Z]的条件。 √
D、输出结果为“pass”, 因为输入的数字4,正则优先匹配到 * 的条件。

for命令

for i in `seq 1 2 10`
do

    echo "1~10之间的奇数分别是:-->$i"

done

while命令

1、已知脚本/home/a.sh内容如下:
    #!/bin/bash
    while true  
    do
            uptime >> /tmp/uptime.log
            sleep 4
    done
在用户终端执行bash /home/a.sh & 命令下列说法正确的是:
A、a.sh脚本会一直在linux后台执行 √
B、a.sh脚本会一直在screen端执行
C、a.sh脚本不会执行因为他没有执行权限 
D、程序无输出,因为脚本没有执行权限

2、这段脚本输出结果为

    #!/bin/bash
    a=3
    b=4
    c=$a+$b
    echo $c

A、输出结果为7
B、输出结果为3+4 √
C、输出结果为$a+$b

3、这段脚本输出结果为
    #!/bin/bash
    a=3
    b=4
    c=$((a+b))
    echo $c

A、7 √
B、a+b
C、3+4
D、空

4、已知脚本/home/a.sh内容如下:
    a=1
    b=2
    while (($a+$b))
    do
            echo 10
            sleep 101
    done
在终端执行 bash /home/a.sh输出的结果为:
A、脚本程序会报错。
B、程序无输出,因为判断条件不为true。
C、每隔十秒钟输出数字10到终端。 √
D、程序无输出,因为脚本没有执行权限

循环语句嵌套

dir="/usr/games"
for folder in $dir 
do 
	for file in $folder/* 
	do	
		if [ -x $file ] 
		then 
			echo " $file" 
		fi
	done
done

四、组合题

1、读写锁

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/pthreadtypes.h>
static pthread_rwlock_t rwlock;//读写锁对象
#define WORK_SIZE 1024
char work_area[WORK_SIZE];//共享全局数据
int time_to_exit;//退出标识符
void *thread_function_read_o(void *arg);//读线程1
void *thread_function_read_t(void *arg);//读线程2
void *thread_function_write_o(void *arg);//写线程1
void *thread_function_write_t(void *arg);//写线程2
    
int main(int argc,char *argv[]) 
{
    int res;
    pthread_t a_thread,b_thread,c_thread,d_thread;
    void *thread_result;
    /*补充代码①,初始化读写锁*/
    
   if (res != 0) 
    {
        perror("rwlock initialization failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, NULL, thread_function_read_o, NULL);//创建线程a_thread
    if (res != 0) 
    {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
     res = pthread_create(&b_thread, NULL, thread_function_read_t, NULL);//创建线程b_thread
    if (res != 0) 
    {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&c_thread, NULL, thread_function_write_o, NULL);//创建线程c_thread
    if (res != 0)
    {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&d_thread, NULL, thread_function_write_t, NULL);//创建线程d_thread
    if (res != 0)
    {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    
     res = pthread_join(a_thread, &thread_result);//等待a_thread线程结束            
     if (res != 0) 
     {
         perror("Thread join failed");
         exit(EXIT_FAILURE);
     }
     res = pthread_join(b_thread, &thread_result);//等待b_thread线程结束
    if (res != 0) 
     {
         perror("Thread join failed");
         exit(EXIT_FAILURE);
     }
    res = pthread_join(c_thread, &thread_result);//等待c_thread线程结束    
    if (res != 0) 
    {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_join(d_thread, &thread_result);//等待d_thread线程结束            
    if (res != 0) 
    {
       perror("Thread join failed");
       exit(EXIT_FAILURE);
    }
   
   /*补充代码②,销毁读写锁*/            
   
    exit(EXIT_SUCCESS);
}
void *thread_function_read_o(void *arg)//读线程1
{
    printf("thread read one try to get lock\n");    
    /*补充代码③,获取读锁*/
    
    while(strncmp("end", work_area, 3) != 0) //比较是否为结束描述符
    {
        printf("this is thread read one.");
        printf("the characters is %s",work_area);//输出
        pthread_rwlock_unlock(&rwlock);//解锁
        sleep(2);
        pthread_rwlock_rdlock(&rwlock);//获取读锁    
        while (work_area[0] == '\0' )          
        {
            pthread_rwlock_unlock(&rwlock);//解锁
            sleep(2);
            pthread_rwlock_rdlock(&rwlock);//获取读锁
        }
    }    
    pthread_rwlock_unlock(&rwlock);//解锁    
    time_to_exit=1;
    pthread_exit(0);
}
 void *thread_function_read_t(void *arg)//读线程2
{
    printf("thread read one try to get lock\n");//获取读锁
    /*补充代码③,获取读锁*/
    
    while(strncmp("end", work_area, 3) != 0) 
    {
        printf("this is thread read two.");
        printf("the characters is %s",work_area);    
        pthread_rwlock_unlock(&rwlock);//解锁            
        sleep(5);
        pthread_rwlock_rdlock(&rwlock);//获取读锁            
        while (work_area[0] == '\0' )          
        {                
            pthread_rwlock_unlock(&rwlock);//解锁
            sleep(5);
            pthread_rwlock_rdlock(&rwlock);//获取读锁    
        }
    }
    pthread_rwlock_unlock(&rwlock);    //解锁
    time_to_exit=1;
    pthread_exit(0);
}
void *thread_function_write_o(void *arg)//写线程1
{
    printf("this is write thread one try to get lock\n");
    while(!time_to_exit) 
    {
        pthread_rwlock_wrlock(&rwlock);//获取写锁
        printf("this is write thread one.\nInput some text. Enter 'end' to finish\n");
        /*补充代码④,读取标准输入流,并存储*/
        
        pthread_rwlock_unlock(&rwlock);//解锁
        sleep(15);
    }
    pthread_rwlock_unlock(&rwlock);//解锁
    pthread_exit(0);
}
void *thread_function_write_t(void *arg)//写线程2
{
    sleep(10);
    while(!time_to_exit)
    {
        pthread_rwlock_wrlock(&rwlock);//获取写锁
        printf("this is write thread two.\nInput some text. Enter 'end' to finish\n"); 
        /*补充代码④,读取标准输入流,并存储*/
        
        pthread_rwlock_unlock(&rwlock);//解锁
        sleep(20);
    }
    pthread_rwlock_unlock(&rwlock);//解锁
    pthread_exit(0);
}
1.1补充代码①,初始化读写锁
  • A.res=pthread_create(&rwlock,NULL);

  • B.res=pthread_rwlock_init(&rwlock,NULL);

    read-write lock initialize : 读写锁初始化

  • C.res=pthread_cond_init(&rwlock,NULL);

  • D.res=pthread_rwlock_create(&rwlock,NULL);

1.2补充代码②,销毁读写锁
  • A.pthread_rwlock_join(&rwlock);

  • B.pthread_cond_destroy(&rwlock);

  • C.pthread_destroy(&rwlock);

  • D.pthread_rwlock_destroy(&rwlock);

    read-write lock destroy : 读写锁摧毁

1.3补充代码③,获取读锁代码
  • A.pthread_rwlock_wrlock(&rwlock);

  • B.pthread_rwlock_rdlock(&rwlock);

    rwlock_rdlock : 读写锁-读锁

  • C.pthread_rdlock_wrlock(&rwlock);

  • D.pthread_rdlock_rwlock(&rwlock);

1.4补充代码④,读取标准输入流,并存储
  • A.fgets(work_area, WORK_SIZE, stdin);

  • B.fgets( WORK_SIZE,work_area, stdin);

  • C.fgets(work_area, WORK_SIZE, stdout);

  • D.fgets(WORK_SIZE,work_area,stdout);

2、生产消费

2.1补全代码①接收端和发送端可分别通过什么命令创建或读取信号量?

A.发送端: if((semid=semget((key_t)123456,1,0666|IPC_CREAT))==-1)

√ 接收端: if((semid=semget((key_t)123456,1,0666|IPC_CREAT))==-1)

B.发送端: if((semid=semget((key_t)123456,1,0666|IPC_CREAT))==-1)

​ 接收端: if((semid=semget((key_t)654321,1,0666|IPC_CREAT))==-1)

C.发送端: if((semid=semget((key_t)123456,1,0666|IPC_CREAT))==-1)

​ 接收端: if((semid=semget((key_t)123456,1,0666|IPC_NOWAIT))==-1)

D.发送端: if((semid=semget((key_t)123456,1,0666|IPC_CREAT))==-1)

​ 接收端: if((semid=semget((key_t)123456,1,0666|IPC_NOWAIT))==-1)

解释如下:

  • key_t 是信号量的键值,用于标识信号量集。
  • 1 表示信号量集中的信号量数量。
  • 0666 是权限标志,表示读写权限。
  • IPC_CREAT 标志表示如果信号量集不存在则创建它。

发送端和接收端都使用相同的键值 (key_t)123456 和相同的标志 0666 | IPC_CREAT,这样它们就能访问到同一个信号量集。

2.2补全代码②接收端和发送端可分别通过什么命令创建或读取共享内存?

A.发送端: shid=shmget((key_t)123456,(size_t)2048,0600|IPC_CREAT);

接收端: shmid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);

B.发送端: shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);

√ 接收端: shmid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);

C.发送端: shid=shmget((key_t)654321,(size_t)2048,0666|IPC_CREAT);

接收端: shmid=shmget((key_t)654321,

D.发送端: shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);

​ 接收端: shmid=shmget((key_t)654321,1,0600|IPC_CREAT);

解释如下:

  • key_t 是共享内存的键值,用于标识共享内存段。
  • (size_t)2048 表示共享内存段的大小。
  • 0600 是权限标志,表示读写权限。
  • IPC_CREAT 标志表示如果共享内存段不存在则创建它。

发送端和接收端都使用相同的键值 (key_t)654321 和相同的标志 0600 | IPC_CREAT,这样它们就能访问到同一个共享内存段。

2.3补全代码③接收端和发送端可分别通过什么命令将共享内存挂载到进程中?

A.发送端: shm_p=shmat(shmid,NULL,0);

​ 接收端: sharem=shmat(shid,NULL,0);

B.发送端: sharem=shmat(shid,NULL,SHM_RND);

​ 接收端: shm_p=shmat(shmid,NULL,SHM_EXEC);

C.发送端: sharem=shmat(shid,NULL,SHM_REMAP);

​ 接收端: shm_p=shmat(shmid,NULL,SHM_RDONLY);

D.发送端: sharem=shmat(shid,NULL,0);

√ 接收端: shm_p=shmat(shmid,NULL,0);

解释如下:

  • shmid 是共享内存的标识符,用于标识共享内存段。
  • NULL 表示让系统自动选择附加点。
  • 0 表示没有特殊标志。

发送端和接收端都使用相同的共享内存标识符 shidshmid,以及相同的标志 0,这样它们就能正确地附加到同一个共享内存段。

2.4下列哪段代码用途是将共享内存与进程卸载?
  • shmdt(shm_p); 用于将共享内存段从当前进程的地址空间中分离。
  • semctl(semid,0,IPC_RMID,0); 用于删除信号量集。
  • shmctl(shmid,IPC_RMID,0) 用于删除共享内存段。
  • strcmp(shm_p,"end") 用于比较两个字符串,不涉及共享内存的操作。

3、临界资源

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex;//全局互斥锁对象 
#define WORK_SIZE 1024
char work_area[WORK_SIZE];//全局共享数据区
int time_to_exit = 0;
int main(int argc,char *argv[]) 
{
    int res;
    pthread_t a_thread;
    void *thread_result;
    res = pthread_mutex_init(&work_mutex, NULL); //初始化互斥锁
    if (res != 0) 
    {
        perror("Mutex initialization failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, NULL, thread_function, NULL);//创建新线程
    if (res != 0) 
    {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }                                                          
    /*补全代码①接收输入前,给互斥锁上锁*/
    printf("Input some text. Enter 'end' to finish\n");
    while(!time_to_exit) //time_to_exit由另一个线程修改
    {
        /*补全代码②从标准输入流读取一行信息*/
        pthread_mutex_unlock(&work_mutex);        //解锁,两个线程抢占互斥锁
        while(1) 
        {
            pthread_mutex_lock(&work_mutex);    //上锁
            if (work_area[0] != '\0') //检查读入的内存输出没有
            {//输出线程将信息输出后将设置work_area[0]!='\0'
                pthread_mutex_unlock(&work_mutex);    //没有输出,解锁
                sleep(1);
            }
            else //没有输出,执行下一轮读入
            {
                break;
            }
        }
    }
    pthread_mutex_unlock(&work_mutex);//解锁
    printf("\nWaiting for thread to finish...\n");  
   /*补全代码③等待另一个线程a_thread结束*/
    if (res != 0) 
    {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
/*补全代码④,销毁互斥锁*/
    
    exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) //子线程执行程序
{
    sleep(1);
    pthread_mutex_lock(&work_mutex);//上锁,抢占资源
    while(strncmp("end", work_area, 3) != 0) //判断是否为结束信息end
    {
        printf("You input %d characters\n", strlen(work_area) -1);//输出输入的字符个数
        printf("the characters is %s",work_area);//输出输入的字符内容
        work_area[0] = '\0';//最后设置第一位为'\0',标识内容已输出
        pthread_mutex_unlock(&work_mutex);//解锁
        sleep(1);
        pthread_mutex_lock(&work_mutex);//上锁
        while (work_area[0] == '\0' ) //判断第1位是否为'\0'
        {//如果为'\0',表示主线程还没有输入数据
         //如果不为'\0',表示有数据,执行下一轮输出操作
            pthread_mutex_unlock(&work_mutex);//解锁,等待
            sleep(1);
            pthread_mutex_lock(&work_mutex);//上锁,再次返回判断
        }
    }
    /*补全代码⑤,置结束标识符,通知主线程操作结束*/
    work_area[0] = '\0';
    pthread_mutex_unlock(&work_mutex);//解锁
    pthread_exit(0);//退出
}
3.1补全代码①接收端和发送端可分别通过什么命令创建或读取信号量
  • pthread_mutex_lock 用于锁定互斥锁,以确保对共享资源的独占访问。
  • pthread_mutex_unlock 用于解锁互斥锁,以释放对共享资源的独占访问。
  • pthread_rwlock 不是有效的POSIX线程函数。
  • pthread_lock 也不是有效的POSIX线程函数。
3.2补全代码②从标准输入流读取一行信息
  • A. fget(work_area, WORK_SIZE, stdin);

  • B.fgets(work_area, WORK_SIZE, stderr);

  • C.fgets(work_area, WORK_SIZE, stdout);

  • D.fgets(work_area, WORK_SIZE, stdin);

解释如下:

  • fgets 用于从指定的输入流读取一行数据并存储到缓冲区中。
  • work_area 是存储读取数据的缓冲区。
  • WORK_SIZE 是缓冲区的大小。
  • stdin 是标准输入流。
3.3补全代码③等待另一个线程a_thread结束
  • A.res = pthread_creat(a_thread, &thread_result);

  • B.res = pthread_join(a_thread, &thread_result);

  • C.res = pthread_destroy(a_thread, &thread_result);

  • D.res = pthread_join(b_thread, &thread_result);

解释如下:

  • pthread_join 用于等待指定的线程结束,并获取该线程的返回值。
  • a_thread 是要等待的线程标识符。
  • &thread_result 是用于存储线程返回值的指针。
3.4补全代码④,销毁互斥锁
  • A.pthread_mutex_destroy(&work_mutex);

  • B.pthread_mutex_lock(&work_mutex);

  • C.pthread_mutex_unlock(&work_mutex);

  • D.pthread_mutex_join(&work_mutex);

3.5补全代码⑤,置结束标识符,通知主线程操作结束
  • A.time_to_exit = 0

  • B.time_to_exit = 1

  • C.res=0

  • D.res=1

解释如下:

  • time_to_exit 是一个共享变量,用于指示操作是否应该结束。
  • time_to_exit 设置为 1 表示通知主线程或其他等待的线程操作已经结束。

4、循环链表

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "pthread.h"
#define BUFFER_SIZE 2//空间大小
struct prodcons //条件信息结构体
{
  int buffer[BUFFER_SIZE];      //生产产品值
  pthread_mutex_t lock;         //互斥锁
  int readpos, writepos;        //读写位置
  pthread_cond_t notempty;      //条件变量,表示非空
  pthread_cond_t notfull;       //条件变量,表示非满
};
/*初始化仓库缓冲区 */
void init(struct prodcons *prod)//初始化
{
  pthread_mutex_init(&prod->lock,NULL);//初始化互斥锁
  pthread_cond_init(&prod->notempty,NULL);//初始化条件变量
  pthread_cond_init(&prod->notfull,NULL);//初始化条件变量
  prod->readpos = 0;//初始化读操作位置
  prod->writepos = 0;//初始化写操作位置
}
void put(struct prodcons * prod, int data)//输入产品子函数
{
        pthread_mutex_lock(&prod->lock);//锁定互斥锁
        /*补全代码①,判断当前测试空间是否已满*/
        {
            printf("producer wait for not full\n");
            pthread_cond_wait(&prod->notfull, &prod->lock);//等待有空间可写
        }
        prod->buffer[prod->writepos] = data;//写数据
        prod->writepos++;//写位置加1
        if (prod->writepos >= BUFFER_SIZE)//写到尾部,返回 
            prod->writepos = 0;
            
        /*补全代码②,发送有数据信号*/
        pthread_mutex_unlock(&prod->lock);//解锁
}
int get(struct prodcons *prod)
{
        int data;
        pthread_mutex_lock(&prod->lock);//锁互斥锁
        /*补全代码③,测试空间内是否有数据*/
        {
            printf("consumer wait for not empty\n");
            pthread_cond_wait(&prod->notempty, &prod->lock);//如果为空,等待
        }
        /*补全代码④读数据,并将读指针加1*/
        if (prod->readpos >= BUFFER_SIZE) //如果读到尾部,返回
            prod->readpos = 0;
        /*补全代码⑤,发送空间内还有空间的信号*/
        pthread_mutex_unlock(&prod->lock);//解锁
        return data;
}
#define OVER (-1)
struct prodcons buffer;
/*--------------------------------------------------------*/
void * producer(void * data)//生产者
{
    int n;
    for (n = 0; n < 5; n++) //生产前5个产品
    {
        printf("producer sleep 1 second......\n");//每1秒生产一个产品
        sleep(1);
        printf("put the %d product\n", n);
        put(&buffer, n);
    }
    for(n=5; n<10; n++)//生产后五个产品
    {
        printf("producer sleep 3 second......\n");//每3秒生产一个产品
        sleep(3);
        printf("put the %d product\n",n);
        put(&buffer,n);
    }
    put(&buffer, OVER);
    printf("producer stopped!\n");
    return NULL;
}
/*--------------------------------------------------------*/
void * consumer(void * data)//消费者
{
    int d=0;
    while (1) 
    {
        printf("consumer sleep 2 second......\n");//每2秒消费一个产品
        sleep(2);
        d=get(&buffer);
        printf("get the %d product\n", d);
//        d = get(&buffer);
        if (d == OVER ) break;
    }
    printf("consumer stopped!\n");
    return NULL;
}
/*--------------------------------------------------------*/
int main(int argc,char *argv[])
{
    pthread_t th_a, th_b;
    void * retval;
    init(&buffer);
    pthread_create(&th_a, NULL, producer, 0);//创建生产线程
    pthread_create(&th_b, NULL, consumer, 0);//创建消费线程
    pthread_join(th_a, &retval);//等待生产线程结束
    pthread_join(th_b, &retval);//等待消费线程结束
    return 0;
}

4.1补全代码①,判断当前空间是否已满
  • A.while ((prod->writepos) % BUFFER_SIZE == prod->readpos);

  • B.while ((prod->readpos + 1) == prod->readpos);

  • C.while ((prod->writepos + 1) % BUFFER_SIZE == prod->readpos);

  • D.while ((prod->readpos + 1) % BUFFER_SIZE == prod->readpos);

解释如下:

  • prod->writepos 是写指针的位置。
  • prod->readpos 是读指针的位置。
  • BUFFER_SIZE 是缓冲区的大小。
  • (prod->writepos + 1) % BUFFER_SIZE 计算下一个写位置,如果这个位置等于 prod->readpos,则表示缓冲区已满。
4.2补全代码②,请发送有数据信号。
  • A.pthread_cond_signal(&prod->notempty);

  • B.pthread_signal(&prod->notempty);

  • C.pthread_cond_signal(&prod->notefull);

  • D.pthread_cond_signal(notempty);

解释如下:

  • pthread_cond_signal 用于唤醒等待指定条件变量的线程。
  • &prod->notempty 是指向条件变量的指针,该条件变量用于表示缓冲区中有数据。
4.3补全代码③,测试空间内是否有数据
  • A.while (writepos == readpos);

  • B.while (prod->notempty == prod->notfull);

  • C.while (prod->writepos == prod->readpos);

  • D.while (notfulll==1);

解释如下:

  • prod->writepos 是写指针的位置。
  • prod->readpos 是读指针的位置。
  • 如果 prod->writepos 等于 prod->readpos,则表示缓冲区为空,没有数据可供消费。
4.4补全代码④,读取数据,并将读指针加1.
  • A.data = prod->buffer[prod->writepos]; prod->readpos++;

  • B.data = prod->buffer[prod->readpos]; readpos++;

  • C.data = prod->buffer[prod->readpos]; prod->readpos++;

  • D.data = prod->writepos; prod->readpos++;

解释如下:

  • prod->buffer[prod->readpos] 表示从缓冲区的当前读位置读取数据。
  • prod->readpos++ 将读指针向前移动一个位置,以便下次读取时指向下一个数据。
4.5补全代码⑤,发送空间内还有空间的信号
  • A.pthread_cond_signal(&prod->notfull);

  • B.pthread_cond_signal(&prod->notempty);

  • C.pthread_cond_signal(notfull);

  • D.pthread_cond_signal(notempty);

解释如下:

  • pthread_cond_signal 用于唤醒等待指定条件变量的线程。
  • &prod->notfull 是指向条件变量的指针,该条件变量用于表示缓冲区中还有空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渣渣盟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值