山东大学操作系统实验问题解决

基础

pv基础

  • 信号量S:
    若大于等于0,则表示可供并发进程使用的资源的实体数;
    若小于0,则表示正在等待使用临界区的进程的个数
    所以初值应该设为大于0
  • 原语:不可中断的程序段
  • P:S-1
    若结果仍然大于等于0,则进程继续执行;
    若结果小于0,则进程阻塞,进入与该信号相对应的队列当中,然后转进程调度。
    V:S+1
    若结果仍然大于0,则进程继续执行;
    若结果小于等于0(注意0的情况在第二种),则从该信号的等待队列中唤醒一个等待进程,然后再返回原来的进程继续执行或转进程调度。
  • 临界资源:每次仅允许一个进程访问的资源,例如打印机,消息缓冲队列,变量,缓冲区等等。
  • 大多数情况下同步已经实现了互斥,同步是在互斥的基础上通过其他机制实现访问者对资源的有序访问(互斥是无序的)。

Makefile

跟我一起写Makefile(一)
跟我一起写Makefile(二)
(系列文章都在评论中有指路)
初次尝试离开IDE编程,对工程的编译有了更深的认识。

这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
make会在当前目录下找名字叫“Makefile”或“makefile”的文件。如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
————————————————
版权声明:本文为CSDN博主「haoel」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haoel/article/details/2886

每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。
更为稳健的做法是:
.PHONY : clean
clean :
-rm edit *.o

前面说过,.PHONY意思表示clean是一个“伪目标”,。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。
———————————————— 版权声明:本文为CSDN博主「haoel」的原创文章,遵循 CC 4.0 BY-SA
版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haoel/article/details/2887

fork()

fork()父子进程共享
fork()父子进程运行优先顺序
在实验中遇到了一点问题,如下代码:

#include <unistd.h> 
#include <sys/types.h> 

main () 
{ 
        pid_t pid; 
        pid=fork(); 
        if (pid < 0) 
            printf("error in fork!"); 
        else if (pid == 0) 
            printf("i am the child process, my process id is %d\n",getpid()); 
        else 
            printf("i am the parent process, my process id is %d\n",getpid()); 
}

在很多文章中,都先输出child process,再输出parent process,而我运行之后结果相反。查找资料fork()父子进程运行先后顺序了解到可能与linux系统版本有关,也有可能原因可能是:

·在多处理系统中,它们可能会同时访问一个cpu;
·在单处理系统中,fork()之后很可能总是先调度父进程(优化性能),但如果恰好父进程的cpu时间片到期了,则执行子进程。

(还发现先输出子进程的资料时间都是比较老的了,估计与版本有关系)

函数

read()
用于文件描述符对应的文件中读取数据,原型:
ssize_t read(int fd,void*buf,size_t count)
#参数说明:
fd: 是文件描述符, 从command line获取数据时,为0
buf: 为读出数据的缓冲区;
count: 为每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移)
#返回值:
成功:返回读出的字节数
失败:返回-1,并设置errno,如果在调用read之前到达文件末尾,则这次read返回0

write()
用于将数据写入到文件描述符对应的文件,原型:
ssize_t write(int fd,const void*buf,size_t count);
#参数说明:
fd:是文件描述符(输出到command line,就是1)
buf:通常是一个字符串,需要写入的字符串 count:是每次写入的字节数
#返回值:
成功:返回写入的字节数
失败:返回-1并设置errno

read()/write()函数的第二个参数是保存在缓冲区的数据/需要写入的数据,在“进程的通信”实验中,用到管道,那么buf参数所代表的就是保存在管道中的数据/要写入管道的数据。

实验四:进程同步实验

基础
  • 在Linux的proc文件系统中有3个虚拟文件动态记录了ipcs命令(包括ipcs -m共享内存情况,ipcs -s信号灯数组,ipcs -q消息队列)显示的当前IPC对象的信息:
    /proc/sysvipc/shm 共享内存 (sharing memory)
    /proc/sysvipc/sem 信号量 (semaphore)
    /proc/sysvipc/msg 消息队列 (message)
    可以利用它们在程序执行时获取有关IPC对象的当前信息。

  • BUFSIZ的值,BUFSIZ为系统默认的缓冲区大小。也可以自己定义#define BUFSIZ 256*。

  • key_t的本质,System V IPC使用key_t值作为它们的名字,在Redhat linux(后续验证默认都在该平台下)下key_t被定义为int类型。

  • IPC结构的键(key)与标识符(ID)

示例
变量

生产者消费者共享缓冲区的变量:buff_key, buff_num, buff_ptr(ptr是共享指针啦…)
生产者放产品位置的共享指针:pput_key, pput_num, pput_ptr
消费者取产品位置的共享指针:cget_key, cget_num, cget_ptr
生产者有关的信号量:cons_key, cmtx_key, cons_sem, cmtx_sem, sem_val, sem_flg, shm_flg

函数
  1. int shmget(key_t key,int size,int flags)
    参数:
    shm_key 共享内存的键值,可以为IPC_PRIVATE(linux进程通信IPC之IPC_PRIVATE与ftok比较),也可以指定一个整数值。
    shm_size 共享内存字节长度
    shm_flags 共享内存权限位
    返回值:调用成功后,若key是用新整数指定并且flags中设置了IPC_CREATE,系统将此值与其他共享内存区的 key 进行比较,如果存在相同的 key ,说明共享内存区已存在,此时返回该共享内存区的标识符,否则新建一个共享内存区并返回其标识符。不成功则返回-1。
    semget,msgget返回值相似,参数略有不同。
  2. int get_ipc_id(char proc_file,key_t key)*
    从/proc/sysvipc/文件系统中获取IPC的id号
    参数中proc_file对应/proc/sysvipc/目录中的IPC文件;key对应要获取的IPC的id号的键值
  3. int set_sem(key_t sem_key,int sem_val,int sem_flg)
    建立一个具有n个信号灯的信号量,返回一个信号灯数组的标识符sem_id
    参数:信号灯数组的键值,信号灯的个数,数组的存取权限
  4. char * set_shm(key_t shm_key,int shm_num,int shm_flg)
    建立一个具有n个字节的共享内存区,返回指向该内存区的首地址的指针shm_buf
  5. int set_msq(key_t msq_key,int msq_flg)
    返回一个消息队列的标识符msq_id
  6. down(int sem_id)
    当sem_id的值是0的时候,不能再减了,阻塞;如果是1如果更高的话,则可以继续。
吸烟者问题(Smoker Problem)

桌子上有容量为1的缓冲区,只能有一种组合在里面。相当于一共有4种同步关系:

  1. 桌子上有组合1,则smoker1取走材料,开始吸烟
  2. 桌子上有组合2,则smoker2取走材料,开始吸烟
  3. 桌子上有组合3,则smoker3取走材料,开始吸烟
  4. 桌子上没有组合,那么吸烟完成之后,供应者将下一个组合放到桌子上
    并且三个吸烟者的吸烟行为互斥,即只能有一个吸烟者吸烟。

思路:将缓冲区的大小设置为1,all_sem(表示缓冲区中的状况),prod_sem(表示生产者同步信号),ab_sem,bc_sem,ac_sem分别表示各个吸烟者的信号。生产者的操作:down(all_sem) down(prod_sem),表示缓冲区被占用了,然后将材料组合放入缓冲区中,再up(producer),并提醒对应的吸烟者。而吸烟者的操作:down(ab_sem),从缓冲区中读取到材料后,down(all_sem),则又回到初始的状态,并且已经变成下一个组合。

实验五:进程互斥实验

IPC之消息队列(struct msqid_ds)

理发店问题思路:理发室有3个理发椅子和3个理发师,有一个容纳4位顾客的沙发,和一间可容纳13位顾客的等候室。情况分为:

  1. 当沙发和等候室都没有人的时候,理发师正在睡觉或者顾客小于3人,正在被理发;
  2. 当沙发上的有人且人数小于4人时,代表等候室中没有人,且有3人正在理发,沙发上的顾客都在等候;
  3. 当沙发上的人数为4人,等候室的人数等于0时,同情况3;
  4. 当等候室的人数大于0时,表示有3位顾客正在理发,沙发上坐着4位顾客,以及等候室中还有顾客在等待;
  5. 当等候室的人数等于13时,表示理发店中的顾客已经满员,不允许有其他顾客进入了。

再补充…*

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值