东华大学操作系统读者写者实验报告
- 格式:docx
- 大小:165.39 KB
- 文档页数:11
读者写者实验报告
读者写者问题是指一个共享固定大小缓冲区的进程间通信问题,其中固定大小的缓冲区被多个读者进程和写者进程所共享。
读者进程从缓冲区中读取数据,而写者进程将数据写入缓冲区。
本实验目的是通过使用互斥锁、条件变量和信号量等同步机制,构建一个读者写者问题的解决方案。
实验环境:
- 操作系统:Linux
-编程语言:C语言
实验步骤:
1.创建共享内存缓冲区,用于读者和写者的数据传递。
2.创建互斥锁,用于保护共享内存缓冲区的访问。
3.创建条件变量,用于读者和写者之间的协调。
4.创建读者进程和写者进程,模拟读者写者的并发操作。
5.在读者进程中,通过互斥锁保护共享内存缓冲区,读取数据,并更新计数器。
6.在写者进程中,通过互斥锁保护共享内存缓冲区,写入数据,并更新计数器。
7.使用条件变量实现读者优先或写者优先的策略。
实验结果:
通过实验,我成功实现了读者写者问题的解决方案。
使用互斥锁可以保护共享资源的访问,防止读者和写者同时访问。
使用条件变量可以实现读者优先或写者优先的策略。
实验总结:
通过本次实验,我深入了解了读者写者问题,并且掌握了使用互斥锁、条件变量和信号量等同步机制来解决读者写者问题的方法。
在实现过程中,我遇到了一些困难,例如死锁和竞争条件等问题。
通
过调试和改进代码,我成功解决了这些问题,提高了程序的稳定性和性能。
在以后的工作中,我会更加注重并发编程的实践,提高自己解决问题
的能力。
操作系统实验报告实验题目:ReaderWriter实验一.实验目的:1.通过编写和调试程序以加深对进程、线程管理方案的理解2.熟悉Windows多线程程序设计方法二.实验原理:读者-写者允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。
文件是各个进程能互斥访问临界资源,读者进程和写者进程之间互斥。
在读者进程中,可以有多个读者读数据库,在读者进程的计数要互斥,避免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。
当读者进程逐渐撤离时,要针对计数变量进行互斥操作,若当前为最后一个读者进程,读完后应唤醒写者进程。
所以应该分四类可能性:1.读者优先权比写者高,并且不用调配。
2.在一个读者已经占有文件的时候,全体读者的优先权才比写者高3.写者的优先权比读者的优先权高4.所有写者的和所有读者有相同的优先权三.实验代码:DataBaseBuffer:import java.awt.*;public class DataBaseBuffer extends Canvas{int[] readWantQ;int[] writerWantQ;String[] wantQ;int frameDelay = 1560;private int writerID;private int readerCount;private int wantCount;private int readerWantCount, writerWantCount;private int writerCount;private int wn, rn; // the number of readers and writersprivate int readTop, readBottom, writerTop, writerBottom;private int wantTop, wantBottom;private Font font;private FontMetrics fm;private boolean readLock = false;private boolean writeLock = false;public DataBaseBuffer( ){resize(500, 300);setBackground(Color.white);font = new Font("TimesRoman", Font.BOLD, 18);fm = getFontMetrics(font);}public void setSize(int readerN, int writerN){rn = readerN;wn = writerN;readTop = readBottom = writerTop = writerBottom = 0;readerCount = writerCount = readerWantCount = writerWantCount = 0;wantTop = wantBottom = 0;wantCount = 0;writerID = 0;readLock = false;writeLock = false;wantQ = new String[rn+wn];writerWantQ = new int[wn];readWantQ = new int[rn];repaint();}public synchronized void enterQueue(String s, int id){wantQ[wantTop] = s + id;wantTop ++;wantCount ++;repaint();}public synchronized void dequeue(String s, int id ){String str;str = s+id;while(!wantQ[0].equals(str)){try{ wait(); } catch(InterruptedException e) { } }for(int i = 0; i < (wantTop-1); i++){wantQ[i] = wantQ[i+1];}wantTop --;wantCount --;repaint();}public synchronized void changePosition(String s, int id) {String str;String tmp;int pos = 0; //to find the posting of 1st writer String wtr;wtr = s+id;while(!(wantQ[pos].equals(wtr))){pos++;}for(int i = 0; i < wantTop; i++){System.out.println(wantQ[i]);}str = wantQ[pos];for(int i = pos; i > 0; i--){wantQ[i] = wantQ[i-1];}wantQ[0] = str;repaint();for(int i = 0; i < wantTop; i++){System.out.println(wantQ[i]);}}public synchronized boolean hasWriterWant(){return (writerWantCount > 0);}public synchronized boolean hasReaderWant(){return (readerWantCount > 0);}public synchronized void acquireReadLock(ReaderWriterApplet applet, int id){readWantQ[readTop] = id; //nums is the index for readWantQreadTop = (readTop+1) % rn;readerWantCount ++;repaint();notifyAll();enterQueue("R", id);applet.r[id].status = 1; //want inapplet.mc.println(applet.r[id].status, "r", id);try{ applet.r[id].sleep(frameDelay);}catch(InterruptedException e) {}if(applet.writerPriority){while(hasWriterWant() || writeLock){applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);try{ wait(); } catch(InterruptedException e) { } }//end of while loop}//end of if statementelse if(applet.readerPriority){while(readWantQ[readBottom] != id){try { wait(); } catch(InterruptedException e) {} }changePosition("R",id);}else{applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);while(!wantQ[wantBottom].equals("R"+id)){try{ wait(); } catch(InterruptedException e) { } }}while(writeLock) //if there is any writer is writing {applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);try{ wait(); } catch(InterruptedException e) { } }if(readLock == false){readLock = true;notifyAll();}readBottom = (readBottom+1) %rn;readerWantCount --;dequeue("R", id);readerCount ++;repaint();applet.r[id].status = 2;applet.mc.println(applet.r[id].status, "r", id);System.out.println("Reader "+id + "is reading");notifyAll();}public synchronized boolean hasReader(){return (readerCount > 0);}public synchronized void releaseReadLock(ReaderWriterApplet applet,int id){readerCount --;notifyAll();if(!hasReader()){readLock = false;notifyAll();applet.r[id].status = 4;applet.mc.println(applet.r[id].status, "r", id);}repaint();}public synchronized void acquireWriteLock(ReaderWriterApplet applet, int id){writerWantQ[writerTop] = id;writerTop=(writerTop+1)%wn;writerWantCount ++;notifyAll();repaint();enterQueue("W", id);applet.w[id].status = 1; //want inapplet.mc.println(applet.w[id].status, "w", id);try{ applet.w[id].sleep(frameDelay); }catch(InterruptedException e) {}if(applet.writerPriority){while(writerWantQ[writerBottom] != id){try{ wait(); } catch(InterruptedException e) { }}changePosition("W", id);while(readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}}else if(applet.readerPriority){while(!(wantQ[wantBottom].equals("W"+id)) || hasReaderWant() || readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}System.out.println("Writer "+ id + " move forward");}else{while(!(wantQ[wantBottom].equals("W"+id))){try{ wait(); } catch(InterruptedException e) { }}while(readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}}writeLock = true;System.out.println("Writer "+ id+ " Got the lock ******");notifyAll();dequeue("W", id);writerBottom = (writerBottom + 1)%wn;writerID = id;writerWantCount --;writerCount++;notifyAll();repaint();applet.w[id].status = 2;applet.mc.println(applet.w[id].status, "w", id);}public synchronized void releaseWriteLock(ReaderWriterApplet applet, int id){System.out.println("Writer " + id + " released the lock");writerCount --;writerID = 0;writeLock = false;notifyAll();repaint();}public void clear(){writerBottom = writerTop = 0;readBottom = readTop = 0;writerWantCount = 0;readerWantCount = 0;readerCount = 0;writerCount = 0;readLock = writeLock = false;writerWantQ = new int[wn];readWantQ = new int[rn];wantQ = new String[wn+rn];wantTop = wantBottom = 0;}public void paint(Graphics g){int xpos = 630;int ypos = 5;g.setFont(new Font("TimesRoman", Font.BOLD, 11));g.setColor(Color.green);g.draw3DRect(xpos, ypos, 10, 10, true);g.fillRect(xpos, ypos, 10, 10);g.drawString("Reading", xpos+15, ypos+10);g.setColor(Color.red);g.draw3DRect(xpos, ypos+14, 10, 10, true);g.fillRect(xpos, ypos+14, 10, 10);g.drawString("Writing", xpos+15, ypos+25);g.setColor(Color.blue);g.draw3DRect(xpos, ypos+28, 10, 10, true);g.fillRect(xpos, ypos+28, 10, 10);g.drawString("Empty", xpos+15, ypos+40);g.setFont(new Font("TimesRoman", Font.BOLD, 14));g.setColor(Color.blue);xpos = 40;ypos = 50;g.drawString("Waiting Queue", xpos-5, ypos-20);int i = wantBottom;for(int j = 0; j < wantCount; j++){if( wantQ[i].equals("W1") || wantQ[i].equals("W2")||wantQ[i].equals("W3")|| wantQ[i].equals("W4")||wantQ[i].equals("W5")){g.setColor(Color.red);g.drawString(wantQ[i], xpos+450-30*j, ypos-18);g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);}if( wantQ[i].equals("R1") || wantQ[i].equals("R2")||wantQ[i].equals("R3")|| wantQ[i].equals("R4")||wantQ[i].equals("R5")){g.setColor(Color.green);g.drawString(wantQ[i], xpos+450-30*j, ypos-18);g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);}i = (i+1) % (wn+rn);}if(readLock) g.setColor(Color.green);else if(writeLock) g.setColor(Color.red);else g.setColor(Color.blue);g.draw3DRect(xpos+250, ypos+20, 100, 100, true);g.fillRect(xpos+250, ypos+20, 100, 100);if(readLock){g.setColor(Color.black);g.drawString("Reading", xpos + 270, ypos+60);}else if(writeLock){g.setColor(Color.black);g.drawString("W " +Integer.toString(writerID), xpos + 280,ypos+45);g.drawString("Writing", xpos + 270, ypos+60);}}}MessageCanvas:import java.awt.*;class MessageCanvas extends Canvas{private Font font;private FontMetrics fm;private int[] writerStatus;private int[] readerStatus;private int msgHeight;private int msgWidth;private int pn, cn;private int frameDelay = 256;public MessageCanvas( ){resize(size().width, 50);setBackground(Color.green);font = new Font("TimesRoman", 1, 18);fm = getFontMetrics(font);msgHeight = fm.getHeight();}public void setMessage(int writerN, int readerN) {pn = writerN;cn = readerN;writerStatus = new int[pn+1];readerStatus = new int[cn+1];repaint();}void println(String s){msgWidth = fm.stringWidth(s);repaint();}void println(int s, String st, int id){if(st.equals("w"))writerStatus[id] = s;elsereaderStatus[id] = s;repaint();}void println(int s, int number, String st, int id){if(st.equals("w")){writerStatus[id] = s;}else{readerStatus[id] = s;}repaint();}public void paint(Graphics g){g.setFont(font);int xpos = 60;int ypos = 40;g.drawString("Status of Readers: ", 60, 20);g.drawString("Status of Writers: ", 360, 20);g.setFont(new Font("TimesRoman", 1, 14));for(int i=1; i<=cn;i++){g.setColor(Color.black);g.drawString("R" + i, xpos, ypos+(15*i+10*(i-1)));if(readerStatus[i] == 0){g.setColor(Color.yellow);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 1){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Want to read", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 3){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 2){g.setColor(Color.blue);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Reading...", xpos+120, ypos+(15*i + 10*(i-1)));}}xpos = 360;ypos = 40;for(int i=1; i<=pn; i++){g.setColor(Color.black);g.drawString("W" + i, xpos, ypos+(15*i+10*(i-1)));if(writerStatus[i] == 0){g.setColor(Color.yellow);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));}else if (writerStatus[i] == 1){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));}else if (writerStatus[i] == 2){g.setColor(Color.blue);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Writing ...", xpos+120, ypos+(15*i + 10*(i-1)));}}}}Reader:public class Reader extends Thread{private DataBaseBuffer buffer;private ReaderWriterApplet tapplet;private int cid;int delay = 6500;int status = 0;public Reader(ReaderWriterApplet applet, DataBaseBuffer db, int id){ buffer = db;tapplet = applet;cid = id;}public void run(){while(true){try{status = 0;tapplet.mc.println(status, "r", cid);sleep((int) (Math.random()*delay));buffer.acquireReadLock(tapplet, cid);sleep((int) (Math.random()*delay));buffer.releaseReadLock(tapplet, cid);} catch(InterruptedException e){System.err.println("Reader Execption " + e.toString());}}}}ReaderWriterApplet:import java.awt.*;import java.awt.event.*;import java.util.*;import java.applet.Applet;import ng.*;public class ReaderWriterApplet extends Applet{private ReaderWriterApplet applet = this;private DataBaseBuffer myBuffer;private int buffersize;private Button fastButton, slowButton, stopButton, startButton, pauseButton, continueButton;private Button stopReaderButton, stopWriterButton;private Panel buttonPanel, priorityPanel, namePanel;private Choice priority, reader, writer;private Thread at;private int readerN = 1;private int writerN = 1;boolean readerPriority = false;boolean writerPriority = false;boolean samePriority = true; //default priority of readers and writers MessageCanvas mc;Reader[] r;Writer[] w;synchronized void startPushed() {notify();}synchronized void stopPushed() {notify();}public void init() {myBuffer = new DataBaseBuffer();mc = new MessageCanvas();resize(800, 600);setLayout(new GridLayout(3, 1));add(myBuffer);add(mc);buttonPanel = new Panel();priorityPanel = new Panel();namePanel = new Panel();Panel bPanel = new Panel(); // to hold all buttons and the labels bPanel.setFont(new Font("TimesRoman", Font.BOLD, 14));bPanel.setLayout(new GridLayout(3, 1));buttonPanel.add(startButton = new Button("START"));buttonPanel.add(stopButton = new Button("STOP"));buttonPanel.add(pauseButton = new Button("PAUSE"));buttonPanel.add(continueButton = new Button("CONTINUE"));buttonPanel.add(fastButton = new Button("FASTER"));buttonPanel.add(slowButton = new Button("SLOWER"));Panel choicePanel = new Panel(); //to hold all the choice boxespriority = new Choice();priority.addItem("Same Priority");priority.addItem("Writers Have Priority");priority.addItem("Readers Have Priority");priority.select("Same Priority");Label priorityLabel = new Label("Priority", 2);priorityLabel.setBackground(Color.lightGray);priorityPanel.add(priorityLabel);priorityPanel.add(priority);choicePanel.add(priorityPanel);reader = new Choice();for(int i = 0; i <=5; i++){reader.addItem(Integer.toString(i));}reader.select("1");Label readerLabel = new Label("Number of Readers", 2);readerLabel.setBackground(Color.lightGray);Panel readerPanel = new Panel();readerPanel.add(readerLabel);readerPanel.add(reader);writer = new Choice();for(int i = 0; i<=5; i++){writer.addItem(Integer.toString(i));}writer.select("1");Label writerLabel = new Label("Number of Writers", 2);writerLabel.setBackground(Color.lightGray);Panel writerPanel = new Panel();writerPanel.add(writerLabel);writerPanel.add(writer);Label nameLabel = new Label("Readers/Writers Animation");nameLabel.setFont(new Font("TimesRoman", Font.BOLD, 18));nameLabel.setForeground(Color.blue);namePanel.add(nameLabel);choicePanel.add(readerPanel);choicePanel.add(writerPanel);bPanel.add(choicePanel);bPanel.add(buttonPanel);bPanel.add(namePanel);add(bPanel);}public boolean action(Event evt, Object arg){if(evt.target == priority){if(arg.equals("Writers Have Priority")){writerPriority = true;readerPriority = false;samePriority = false;}else if(arg.equals("Readers Have Priority")) {readerPriority = true;writerPriority = false;samePriority = false;}else{readerPriority = false;writerPriority = false;samePriority = false;}return true;}else if(evt.target == reader){readerN = Integer.parseInt(arg.toString());return true;}else if(evt.target == writer){writerN = Integer.parseInt(arg.toString());return true;}else if(arg.equals("FASTER")){int newDelay;if(readerN != 0) newDelay = r[1].delay;else newDelay = w[1].delay;newDelay /= 2;newDelay = newDelay < 100 ? 100: newDelay;for(int i = 1; i <= readerN; i++){r[i].delay = newDelay;for(int i = 1; i <= writerN; i++){w[i].delay = newDelay;}return true;}else if(arg.equals("SLOWER")){int newDelay;if(readerN !=0) newDelay = w[1].delay;else newDelay = r[1].delay;newDelay *= 2;for(int i = 1; i <= readerN; i++){r[i].delay = newDelay;}for(int i = 1; i <= writerN; i++){w[i].delay = newDelay;}return true;}else if(arg.equals("PAUSE")){for(int i = 1; i <= readerN; i++){r[i].suspend();}for(int i = 1; i <= writerN; i++){w[i].suspend();}fastButton.setEnabled(false);slowButton.setEnabled(false);return true;}else if(arg.equals("CONTINUE")){for(int i = 1; i <= readerN; i++){if(r[i].isAlive()) r[i].resume();}for(int i = 1; i <= writerN; i++)if(w[i].isAlive()) w[i].resume();}fastButton.setEnabled(true);slowButton.setEnabled(true);return true;}else if(arg.equals("START")){r = new Reader[readerN+1]; //Reader[0] is a dummy slotw = new Writer[writerN+1];System.out.println("readers: "+readerN+" writers: " + writerN);mc.setMessage(writerN, readerN);myBuffer.setSize(readerN, writerN);for(int i = 1; i <= readerN; i++){r[i] = new Reader(applet, myBuffer, i);}for(int i = 1; i <= writerN; i++){w[i] = new Writer(applet, myBuffer, i);}for(int i = 1; i <= writerN; i++){w[i].start();}for(int i = 1; i <= readerN; i++){r[i].start();}fastButton.setEnabled(true);slowButton.setEnabled(true);startButton.setEnabled(false);reader.setEnabled(false);writer.setEnabled(false);priority.setEnabled(false);applet.startPushed();return true;}else if(arg.equals("STOP")){for(int i = 1; i <= readerN; i++){if(r[i].isAlive())r[i].stop();r[i] = null;}for(int i = 1; i <= writerN; i++){if(w[i].isAlive())w[i].stop();w[i] = null;}applet.stopPushed();startButton.setEnabled(true);fastButton.setEnabled(true);slowButton.setEnabled(true);reader.setEnabled(true);writer.setEnabled(true);priority.setEnabled(true);if(at != null) at.stop();at = null;return true;}else{ return false;}}}Writer:public class Writer extends Thread{private DataBaseBuffer buffer;private ReaderWriterApplet tapplet;private int id;int delay = 6500;int status = 0;public Writer(ReaderWriterApplet applet, DataBaseBuffer db, int id){ buffer = db;tapplet = applet;this.id = id;}public void run(){while(true){try{status = 0;tapplet.mc.println(status, "w", id);sleep((int)(Math.random()*delay));buffer.acquireWriteLock(tapplet, id);sleep((int) (Math.random()*delay));buffer.releaseWriteLock(tapplet, id);} catch(InterruptedException e){System.err.println("Execption " + e.toString());}}}}四.实验结果:运行如下:。
实验内容1、定义一个数据缓存buffer 及用于实现同步互斥的信号量。
2、定义一个读者函数:● 当有写者在占用buffer 时,读者应该等待,直到写者不再使用该buffer 。
● 当有其他读者在占用buffer 时,读者可对buffer 进行读取操作。
● 当buffer 中有数据时,则从其中读取一个数据,并显示然后退出。
● 当buffer 中没有数据时,应等待,直到buffer 中有数据可读。
3、定义一个写者函数● 当有读者在占用buffer 时,写者应该等待,直到所有的读者都退出为止。
● 当有其他写者占用buffer 时,该写者应该等待,直到占用buffer 的写者退出为止。
● 当buffer 有空闲时,写者应该在buffer 中写入一个数据并退出。
● 当buffer 满时,写者应该等待,直到buffer 有空闲为止。
4、定义主函数,在其中可以任意创建读者与写者。
● 可根据用户输入创建读者或写者进程(线程)。
5、用户界面2. 写者: 开始 读出的内容: 1. 读者:开始 结束 2 1 读者队列等待结束写出的内容: Hello world !结束实验当堂所要完成事情列表:1.调试程序使其在读者优先模式下可以运行并且能实现基本的功能得出正确的结果:能够实现读写互斥,写写互斥,读读不互斥,一个进程结束能够唤醒等待队列中的进程(先读者队列后写着队列)2.根据实验要求完善功能:由用户决定写者向缓冲区中写入的内容,读者能够读出并显示出来;当缓冲区中没有数据时,读者要等待,直到缓冲区中有数据才能读3.根据“读者优先”加以改变,增加一个“写者优先”模式,并且由用户来选择模式源代码:#include<stdio.h>#include<stdlib.h>int rcount=0;//正在读的读者数量int wcount=0;//写者队列中等待写操作的写者数量int read_id=0;//读进程号int write_id=0;//写进程号int w=1;//读写互斥信号量char temp[300] = {'\0'};int choice; //用户选择读者优先OR写者优先int sign; //标识temp空的信号量 0表示temp空void WFwakeup();void RFwakeup();struct rqueue{//读者等待队列int readers[200];int index;}rq;struct wqueue{//写者等待队列int writers[200];int index;}wq;/*void first(){ //初始化int i;rq.index = 0;wq.index = 0;for(i = 0;i<20;i++){rq.readers[i] = 0;wq.writers[i] = 0;}}*///*******************************************读进程读操作void read(){int i = 0;read_id++;if(rcount == 0){//当前没有读进程在读可能有写进程在写可能CPU空闲if(w==1) {//如果CPU空闲,读者拿到CPUw--;// 相当于一个P操作rcount++;if(temp[0] == '\0'){sign = 0;if(choice == 1){rq.readers[rq.index++]=read_id;//将读者进程加入等待队列RFwakeup();return;}else{rq.readers[rq.index++]=read_id;//将读者进程加入等待队列WFwakeup();return;}}//ifprintf("读者%d正在读\n",read_id);for(i = 0;i < 300;i++){//读取temp内容即写者写的内容if(temp[i] == '\0'){printf("\n");return;}//ifprintf("%c",temp[i]);}//for}//ifelse{//写者线程正在执行printf("!有写者在写不能读!\n");rq.readers[rq.index++]=read_id;//将读者进程加入等待队列}//else}//ifelse{//rcount !=1 则知道当前已经有读者在读,读读不互斥,则这个读者可以直接进来了读printf("读者%d正在读\n",read_id);for(i = 0;i < 300;i++){if(temp[i] == '\0'){printf("\n");return;}printf("%c",temp[i]);}//for}//else}//***************************写进程写操作void write(){write_id++;if(w == 0){if(rcount != 0 ){//有读者进程在执行printf("!有读者在读不能写!\n");wq.writers[wq.index++]=write_id;//将写者进程加入等待队列wcount++;return;}if(rcount == 0 ){//rcount == 0则当前无读者,但w = 0,所以有写者在写printf("!有写者在写不能写!\n");wq.writers[wq.index++]=write_id;//将写者进程加入等待队列wcount++;return;}}if(w == 1){w--;printf("写者%d正在写\n请输入要写的内容",write_id);scanf("%s",temp);//while}//if}//************************读者优先时唤醒进程void RFwakeup(){int i = 0;int j = 0;int m,n;m = rq.index;// n = wq.index;if(rcount == 0){//当前无读进程,是写者在写 --》停止运行写进程bool reader_wait=false;w=1;printf("写者已经写完\n");sign = 1;//temp中已经有内容要置1for(i=0;i<=m;i++){// i ndex为当前读者队列中的等待进程数if(rq.readers[i]!=0){reader_wait=true; //确实有读者在等待printf("等待的读者%d正在读\n",rq.readers[i]);w = 0;for(j = 0;j < 300;j++){if(temp[j] == '\0'){printf("\n");break;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0;rcount++;rq.index--;}//if}//forif(!reader_wait){//没有读者等待,看是否有写者等待for(int i=0;i<=wq.index;i++){//检查写者等待队列if(wq.writers[i]!=0){w = 0;printf("等待的写者%d正在写\n请输入要写入的内容",wq.writers[i]);scanf("%s",temp);wq.writers[i]=0;wcount--;break;}//if}//for}//if// return;}//ifelse{//rcount != 0读者正在读,stop读此时若有等待必为写者rcount=0;w = 1;if(sign == 0){printf("缓冲区空等待写者\n");return;}else{printf("读者已经读完\n");for(int i=0;i<=wq.index;i++){// 检查写者等待队列if(wq.writers[i]!=0){w = 0;printf("等待的写者%d正在写\n请输入要写入的内容",wq.writers[i]);scanf("%s",temp);wq.writers[i]=0;wcount--;break;}//if}//for}}//else}//******************************************写者优先唤醒void WFwakeup(){int i = 0;int j = 0;int m,n;m = rq.index;//n = wq.index;if(rcount == 0){//当前无读进程,是写者在写 --》停止运行写进程bool writer_wait=false;w=1;printf("写者已经写完\n");sign = 1;//temp中已经有内容要置1for(i=0;i<=wq.index;i++){// index为当前写者队列中的等待进程数if(wq.writers[i]!=0){writer_wait=true; //确实有写者在等待printf("等待的写者%d正在写\n 请输入要写的内容\n",wq.writers[i]);w = 0;scanf("%s",temp);wq.writers[i]=0;wcount--;break;}}if(!writer_wait){//没有xie者等待,看是否有du者等待for(int i=0;i<=m;i++){//检查写者等待队列if(rq.readers[i]!=0){w = 0;printf("等待的读者%d正在读\n",rq.readers[i]);for(j = 0;j < 300;j++){if(temp[j] == '\0'){printf("\n");rq.index--;break;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0;rcount++;}//if}//for}//if// return;}//ifelse{//rcount != 0读者正在读,stop读此时若有等待必为写者rcount=0;w = 1;printf("读者已经读完\n");for(int i=0;i<=wq.index;i++){// 检查写者等待队列if(wq.writers[i]!=0){w = 0;printf("等待的写者%d正在写\n请输入要写入的内容",wq.writers[i]);scanf("%s",temp);wq.writers[i]=0;wcount--;break;}//if}//for}}void menu1(){char i;printf(" 1-创建读者进程\n 2-创建写者进程\n 3-结束当前执行的进程\n 4-退出程序\n");printf("*******************************************\n");do{printf("当前队列中有读者: %d个写者: %d个\n",rq.index,wcount);printf("*******************************************\n");printf(" ----->");scanf("%s",&i);switch(i){case '1':read();break;case '2':write();break;case '3':RFwakeup();break;case '4':exit(0);default:printf("输入错误请重新输入\n");}}while(true);}void menu2(){char i;printf(" 1-创建读者进程\n 2-创建写者进程\n 3-结束当前执行的进程\n 4-退出程序\n");printf("*******************************************\n");do{printf("当前队列中有读者: %d个写者: %d个\n",rq.index,wcount);printf("*******************************************\n");printf(" ----->");scanf("%s",&i);switch(i){case '1':read();break;case '2':write();break;case '3':WFwakeup();break;case '4':exit(0);default:printf("输入错误请重新输入\n");}}while(true);}void main(){printf("*************************************************** ***********************\n");printf(" 20092104实验一\n 1.读者优先\n 2.写者优先\n");scanf("%d",&choice);while(1){if(choice == 1)menu1();if(choice == 2)menu2();if(choice != 1 && choice != 2){printf("输入错误请重新输入\n");scanf("%d",&choice);}}}实验流程图:N Y开始 读者优先 写者优先 读操作 写操作 是否有读者在读进行读操作 YCPU 是否空闲 缓冲区是否为空有写者 读者入队 N Y 入读者等待队列 调用读者优先唤醒 读操作 N 是否有读者在读 有读者 写者入队 Y N Cpu 是否空闲进行写操作 有写者,写操作入队 YN 退出 结束 读者优先唤醒 写者优先唤醒核心部分设计思路:读者优先唤醒当前有无读者在读有无读者等待N有无写者等待N 读者出队进行读操作直到读者队空Y进行写操作 YN 返回Y缓冲区是否为空YN写者优先唤醒当前有无读者在读有无写者等待N有无读者等待N 写者出队进行写操作直到写者队空Y进行读操作直到读者队列为空YN 返回YN写者队列是否为空进行写操作直到写者队列为空Y有读者说明若有等待必为写者分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。
操作系统实验报告心得体会范文大全(8篇)操作系统实验报告心得体会范文大全篇一:通过这一学期学习,才慢慢接触专业课。
刚开始觉得挺难得我都有点不想学这个专业了,慢慢的我觉得有趣多了。
虽然我学的不是很好,最起码我能给自己装系统了。
我给自己的电脑装过window7、xp系统。
从一开始连个cmos设置都不会进去,到现在能装各种机型的系统。
让我最高兴的事是我会建立网站了,以及能制作出复杂点的,漂亮的网页了。
从刚开始学装windowserver20xx时,我真的懵懵懂懂的,那开始是真的不想学这个专业了,那段时间还学java编程,我真的快崩溃了,后悔自己干嘛学这个专业,我根本就是没有天赋,感觉大学这四年完蛋了,大一大二还没有感觉,现在真实的感受到了,但后来发现,我是越来越感觉有兴趣了,只要肯付出课后肯钻研,就一定会有一点收获的。
通过这次网页课程设计激发学习兴趣,调动学习的自觉性,自己动脑、动手,动口,运用网络资源,结合教材及老师的指导,通过自身的实践,创作出积聚个人风格、个性的个人网页。
总体来说,整个学期的学习过程,我学会了很多知识,在此次网页设计中,我充分利用了这次设计的机会,全心全意投入到网页世界,去不断的学习,去不断的探索;同时去不断的充实,去不断的完善自我,在网络的天空下逐渐的美化自己的人生!做好页面,并不是一件容易的事,它包括个人主页的选题、内容采集整理、图片的处理、页面的排版设置、背景及其整套网页的色调等很多东西。
本次课程设计不是很好,页面过于简单,创新意识反面薄弱,这是我需要提高的地方。
需要学的地方还有很多,需要有耐心、坚持,不断的学习,综合运用多种知识,才能设计出好的web页面。
总体来说,通过这次的对网页和网站课程设计,有收获也有遗憾、不足的地方,但我想,我已经迈入了网页设计的大门,只要我再认真努力的去学习,去提高,凭借我对网页设计的热情和执着,我将来设计出的网页会更加专业,更完善。
操作系统实验报告心得体会范文大全篇二:转眼间,学习了一个学期的计算机操作系统课程即将结束。
操作系统上机实验报告学院:计算机科学与技术学院专业:计算机科学与技术学号:姓名:读者-写者的读写限制(包括读者优先和写者优先)1)写-写互斥,即不能有两个写者同时进行写操作2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写3)读读允许,即可以有2个以上的读者同时读读者优先的限制:如果一个读者申请读操作时,已经有一个读者在读,则该读者可以直接读写者优先的限制:如果一个读者申请读操作时,有写者在等待访问共享资源时,则该读者要等到没有写者处于等的状态时才能开始读操作代码部分:#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <signal.h>#include <unistd.h>#include <stdarg.h>#include <assert.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <time.h>/*** @struct SHM_ACCESS* @brief 读者写者访问控制结构*/typedef struct _SHM_ACCESS {int reader_count; /**< 读者计数器 */int reader_mutex; /**< 读者互斥量 */int writer_mutex; /**< 写者互斥量 */} SHM_ACCESS;typedef struct _READER_WRITER_SHM {SHM_ACCESS shm_access;int shm_reader;int shm_writer;} READER_WRITER_SHM;static sig_atomic_t term_flag = 0;intlogv(const char *fmt, ...){int n;struct timeval tv;struct tm lt;char buf[14];va_list ap;gettimeofday(&tv, 0);lt = *localtime(&_sec);strftime(buf, sizeof(buf), "%H:%M:%S.", <);snprintf(buf + 9, sizeof(buf) - 9, "%03d", (int)(_usec / 1000)); n = printf("%s ", buf);va_start(ap, fmt);n += vprintf(fmt, ap);va_end(ap);return n;}/** System V IPC 函数的简化接口*/intsem_p(int semid){int rc;struct sembuf buf;buf.sem_num = 0;buf.sem_op = -1;buf.sem_flg = SEM_UNDO;for (;;) {rc = semop(semid, &buf, 1); if (0 == rc)break;if (rc < 0) {if (EINTR == errno)continue;else {assert(0);}}}}intsem_v(int semid){int rc;struct sembuf buf;buf.sem_num = 0;buf.sem_op = +1;buf.sem_flg = SEM_UNDO;for (;;) {rc = semop(semid, &buf, 1); if (0 == rc)break;if (rc < 0) {if (EINTR == errno)continue;else {assert(0);}}}return rc;}intsem_get(const char *path, int id){int semid;key_t semkey;int rc;union semun {int val;struct semid_ds *buf;unsigned short *array;} arg;semkey = ftok(path, id);if ((key_t)-1 == semkey) {return (-1);}semid = semget(semkey, 1, IPC_CREAT | SEM_R | SEM_A); if (semid < 0)return semid;arg.val = 1;rc = semctl(semid, 0, SETVAL, arg);assert(0 == rc);return semid;}intsem_del(const char *path, int id){int semid;key_t semkey;int rc;semkey = ftok(path, id);if ((key_t)-1 == semkey) {return (-1);}semid = semget(semkey, 1, SEM_R | SEM_A);return sem_rmid(semid);}intsem_rmid(int semid){int rc;rc = semctl(semid, 0, IPC_RMID);return rc;}intshm_get(const char *path, int id, size_t size){int shmid;key_t semkey;semkey = ftok(path, id);if ((key_t)-1 == semkey) {return (-1);}shmid = shmget(semkey, size, IPC_CREAT | SHM_R | SHM_W); if (shmid < 0)return shmid;return shmid;}/** 共享内存读写控制函数*/intLockShmForWrite(SHM_ACCESS *p_access){sem_p(p_access->writer_mutex);return (0);}intUnLockShmForWrite(SHM_ACCESS *p_access){sem_v(p_access->writer_mutex);return (0);}intLockShmForRead(SHM_ACCESS *p_access){sem_p(p_access->reader_mutex);p_access->reader_count++;logv("reader_count = %d\n", p_access->reader_count); if (1 == p_access->reader_count) {/* 第一个读进程 */sem_p(p_access->writer_mutex);}sem_v(p_access->reader_mutex);return (0);}intUnLockShmForRead(SHM_ACCESS *p_access){sem_p(p_access->reader_mutex);p_access->reader_count--;logv("reader_count = %d\n", p_access->reader_count); if (0 == p_access->reader_count) {/* 最后一个读进程 */sem_v(p_access->writer_mutex);}sem_v(p_access->reader_mutex);return (0);}void*shm_at(int shmid){return shmat(shmid, NULL, 0);}intshm_dt(const void *shmaddr){return shmdt(shmaddr);}intshm_rmid(int shmid){return shmctl(shmid, IPC_RMID, NULL);}void(*Signal(int sig, void (*func)(int)))(int){struct sigaction act, oact;act.sa_handler = func;sigemptyset(&act.sa_mask);act.sa_flags = 0;#ifdef SA_INTERRUPTact.sa_flags |= SA_INTERRUPT;#endifif (sigaction(sig, &act, &oact) < 0)return(SIG_ERR);return(oact.sa_handler);}#define KEY_FILE "KEY_FILE"intstarter(void){int shmid;int semid;READER_WRITER_SHM *ptr;shmid = shm_get(KEY_FILE, 1, sizeof(READER_WRITER_SHM)); ptr = (READER_WRITER_SHM *)shm_at(shmid);semid = sem_get(KEY_FILE, 2);ptr->shm_access.reader_mutex = semid;ptr->shm_access.reader_count = 0;semid = sem_get(KEY_FILE, 3);ptr->shm_access.writer_mutex = semid;return 0;}intcleaner(void){int shmid;int semid;READER_WRITER_SHM *ptr;sem_del(KEY_FILE, 3);sem_del(KEY_FILE, 2);shmid = shm_get(KEY_FILE, 1, sizeof(READER_WRITER_SHM)); shm_rmid(shmid);return 0;}voidsig_term(int sig){term_flag++;}voidsig_intr(int sig){}intreader(void){int shmid;pid_t pid;READER_WRITER_SHM *ptr;shmid = shm_get(KEY_FILE, 1, sizeof(READER_WRITER_SHM)); ptr = (READER_WRITER_SHM *)shm_at(shmid);pid = getpid();srand(time(0) + pid);while (!term_flag) {sleep(rand() % 20);logv("reader-%10d come\n", (int)pid);LockShmForRead(&ptr->shm_access);logv("reader-%10d read begin\n", (int)pid);sleep(rand() % 10);logv("reader-%10d read end\n", (int)pid);UnLockShmForRead(&ptr->shm_access);}return 0;}intwriter(void){int shmid;pid_t pid;READER_WRITER_SHM *ptr;shmid = shm_get(KEY_FILE, 1, sizeof(READER_WRITER_SHM)); ptr = (READER_WRITER_SHM *)shm_at(shmid);pid = getpid();srand(time(0) + pid);while (!term_flag) {sleep(rand() % 20);logv("writer-%10d come\n", (int)pid);LockShmForWrite(&ptr->shm_access);logv("writer-%10d write begin\n", (int)pid);sleep(rand() % 10);logv("writer-%10d write end\n", (int)pid);UnLockShmForWrite(&ptr->shm_access);}return 0;}#define M 8#define N 2intmain(int argc, char *argv[]) {int i, m, n;pid_t pid[M + N];m = M, n = N;Signal(SIGTERM, &sig_term);starter();for (i = 0; i < m; i++) { pid[i] = fork();if (pid[i] == 0) {reader();exit(0);} else {continue;}}for (i = 0; i < n; i++) { pid[i + m] = fork();if (pid[i + m] == 0) { writer();exit(0);} else {continue;}}Signal(SIGINT, &sig_intr);pause();for (i = 0; i < M + N; i++) kill(pid[i], SIGTERM);for (i = 0; i < M + N; i++)waitpid(pid[i], NULL, 0);cleaner();return 0;}。
《操作系统原理》课程设计课程设计起止时间:2009年11月30日至12月11日指导教师:成绩:课程设计成绩评定表一.设计说明(四号,宋体,加粗)通过学习操作系统,与之前的语句基础相结合,用C语言来编写读者写着问题。
读者写者问题(read—write problem)是一个经典的并发程序设计问题。
有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读操作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写操作之前不允许其他读者或者写者工作;(4)写者执行写操作前,应让已有的写者和读者全部退出。
二.工作原理(四号,宋体,加粗)读者和写者问题是典型是经典的进程同步问题,进程同步任务是使并发的诸进程之间有效的共享资源,相互合作,从而保证程序的可再现性。
在读者—写者问题中,允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但绝不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。
文件是诸进程能互斥访问临界资源,读者进程和写者进程,写者进程和写者进程之间的互斥。
在读者进程中,可以有多个读者在读数据库,在读者进程的计数要互斥,以免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。
当读者进程逐渐撤离时,也要针对计数变量进行互斥操作,若当前为最后一个读者进程时,读完后,则唤醒写者进程。
当写者进程在进行写操作时,可以封锁其他读者或写者进程,当写操作完成时,唤醒其他读者或写者进程。
所以分析了以下4种可能发生的情况:第 1 种情况: 读者的优先权比写者高,而且,不用调配。
所有读者的优先权都比写者的优先权高,而且,不用调配。
一个读者需要等待的唯一情况是,一个写者已经占用了文件。
一个写者可以取得文件的条件是,没有一个读者处在等待状态或正在读文件。
允许读者们结盟,以便能长期占用文件,而禁止写者的写。
第 2 种情况: 在一个读者已经占有了文件的时候,全体读者的优先权才比写者高。
操作系统实验报告在学习计算机科学的过程中,操作系统是必不可少的一门课程。
为了更好地理解操作系统的各种概念和运作原理,我们通常需要进行实验来加深对知识的理解。
本篇文章主要介绍一次操作系统实验的报告。
实验名称:进程管理与调度实验实验目的:1. 理解进程管理的基本概念和原理。
2. 学习进程调度的算法及其实现原理。
3. 掌握在操作系统中实现进程管理与调度的方法。
实验环境:本次实验的环境为在Ubuntu系统下使用C语言编程实现。
实验内容:1. 进程管理在本次实验中,我们主要针对进程的创建、撤销、休眠和唤醒等基本操作进行了学习。
其中,进程创建的过程包括了进程控制块的初始化、资源的分配和进程调度等。
进程的撤销则需要对进程控制块进行清除和释放资源的操作。
此外,进程休眠和唤醒还需要使用信号量等同步机制来实现。
2. 进程调度在操作系统中,为了保证多个进程之间的公平性和平等性,需要使用进程调度来进行资源的合理分配。
具体来说,本次实验中我们主要学习了轮询、优先级和反馈队列三种进程调度算法,并通过程序的实现,加深了对其原理的理解。
实验结果:经过本次实验,我们成功实现了进程管理和调度的程序,并且对于其中的原理和算法有了更深入的理解。
在实验过程中,我们还遇到了各种问题和挑战,例如进程控制块的设计、死锁的预防等,但是通过团队协作和不断探索,最终都克服了这些问题。
同时,还通过本次实验深刻领悟到了操作系统的重要性,以及对于计算机科学专业而言,在操作系统上的学习和掌握是必不可少的。
结语:操作系统实验是我们学习计算机科学的关键环节之一,它能够让我们更深入地理解操作系统的原理和关键概念。
通过本次实验,我们不仅学会了如何实现进程管理和调度,也学会了如何遇到问题时积极寻找解决方案。
相信这些经验和技能可以在我们未来的学习和工作中给予帮助和指引。
操作系统原理实验报告实验名称:操作系统姓名: XXX学号: xxxxxxxxxx班级: xxx指导老师: xxx一、实验内容在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验目的在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
三、实验原理1).读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
操作系统读者写者实验报告一、实验目的通过实验理解读者写者问题的实现原理,掌握相关的同步机制,实现读者写者问题的经典解法,并对比不同解法的优缺点。
二、实验原理1.读者写者问题读者写者问题是指在多个线程同时读写一个共享数据的情况下可能出现的问题。
其问题的核心在于多个读线程可以同时读,但只能有一个写线程能够写,并且在写操作过程中不能有任何的读操作。
2.互斥与同步为了解决读者写者问题,在多线程并发读写共享数据时,需要使用互斥与同步机制来保证数据的完整性和一致性。
-互斥:通过锁机制来保证只允许一个线程进入临界区,其他线程需要等待锁的释放。
-同步:通过信号量等机制来保证线程按照一定顺序执行。
三、实验步骤本次实验中将实现两个版本的读者写者问题解决方案:一是使用互斥锁和条件变量,二是使用信号量。
1.使用互斥锁和条件变量(1)定义全局变量和互斥锁:共享数据、读者数目、互斥锁、写者条件变量、读者条件变量。
(2)初始化互斥锁和条件变量。
(3)写者线程的实现:获取互斥锁,判断当前是否有读者或写者,如果有则等待条件变量,然后进行写操作,释放互斥锁。
(4)读者线程的实现:获取互斥锁,判断是否有写者,如果有则等待条件变量,否则增加读者数目并释放互斥锁,进行读操作。
(5)测试程序的运行并输出结果。
2.使用信号量(1)定义全局变量和信号量:共享数据、读者信号量、写者信号量、用于保护读者数目和写者数目的互斥信号量。
(2)初始化信号量和互斥信号量。
(3)写者线程的实现:首先获取写者互斥信号量,然后获取写者信号量,进行写操作,释放写者信号量和写者互斥信号量。
(4)读者线程的实现:首先获取读者互斥信号量,然后增加读者数目,如果是第一个读者则获取写者信号量,然后进行读操作,释放读者信号量和读者互斥信号量,如果是最后一个读者则释放写者信号量。
(5)测试程序的运行并输出结果。
四、实验结果与分析通过对比两种解决方案,可以得出以下结论:1.使用互斥锁和条件变量的解决方案相对较为简单,但可能存在饥饿问题,即可能会导致一些线程一直无法访问共享资源。
东华大学计算机学院操作系统实验报告实验名称:读者写者问题姓名:姜元杰学号:111310228班级:计算机1102指导老师:李继云报告日期:2013/10/12一、实验概述1.实验目标在Windows系统平台下,了解Windows编程基本知识,通过创建线程等一系列操作实现进程同步经典问题——读者写者问题。
2.实验要求在Windows7环境下,创建一个控制台进程,此进程包含n个线程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验内容1.设计思路通过仔细分析问题,实验实现内容分别为读者优先部分与写者优先部分。
通过建立统一的线程数组存储所有待创建线程,并在系统后台分别存于可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
通过程序代码实现读读允许,读写互斥,写写互斥。
对于读者优先部分,引入Mutex信号量和临界区对象RP_Writer实现。
读者优先指的是除非有写者在写文件,否则读者不需要等待。
目录一设计概述 (2)二设计目的与内容 (3)三设计分析 (4)四程序实现 (5)五程序调试 (6)六结果分析和讨论 (6)七心得体会 (7)八源代码 (7)一设计概述所谓读者写者问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前是否可操作。
信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则是这一机制的一个经典范例。
与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。
为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。
当有RN个读者进入读后,L便减为0,第RN+1 个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。
对利用信号量来解决读者—写者问题的描述如下:Var RN integer;L,mx:semaphore: =RN,1;BeginParbeginReader :beginRepeatSwait(L,1,1);Swait(mx,1,0);.Perform reader operation;Ssignal(L,1);Until false;EndWriter :beginRepeatSwait(mx ,1,1,l,RN,0);Perform writer operation;Ssignal(mx,1);Until false;EndParendEnd其中,Swait(mx,1,0)语句起着开关作用,只要无Writer进程进入些,mx=1,reader进程就都可以进入读。
读者写者问题实验报告1.实验目的:掌握读者写者问题的基本概念和操作实现方法。
2.实验原理:(1)读者写者问题:1.读者优先:若读者进程正在读文件,写者进程需等待。
2.写者优先:若写者进程正在写文件,读者进程需等待。
3.公平竞争:读写者进程均有机会访问文件。
(2)进程同步:1.信号量:能够同步进程的执行,性能较好。
2.互斥量:能够同步进程的执行,提供了更细粒度的控制。
3.条件变量:让进程能够进行相互之间的协作。
3.实验内容:(1)依照读者写者问题的操作实现方法,采用信号量机制,编写读者进程和写者进程。
(2)测试不同读者写者优先级下程序的执行情况。
4.实验步骤:(1)设计程序架构:1.使用信号量实现读者写者访问文件的同步操作;2.设计Readers和Writers两个类分别实现读者和写者进程的操作。
(2)实现程序:1.编写读者进程,在进程对文件进行读操作之前使用信号量P操作,读取完成后使用信号量V操作;2.编写写者进程,在进程对文件进行写操作之前使用信号量P操作,写入完成后使用信号量V操作;3.设计信号量的初始值,以实现不同读者写者优先级下程序的执行情况。
(3)测试程序:在有多个读者进程和多个写者进程的情况下,测试不同读者写者优先级下程序的执行情况。
5.实验结果:(1)读者优先:读者优先的情况下,不管读者进程和写者进程的数量如何设置,读者总是有后进先出的机会访问文件。
(2)写者优先:写者优先的情况下,不管读者进程和写者进程的数量如何设置,写者总是有先进先出的机会访问文件。
(3)公平竞争:公平竞争的情况下,读者或写者进程均有机会访问文件。
6.实验结论:(1)在实现读者写者问题的过程中,需要采用进程同步技术来确保进程之间的正确协作。
(2)信号量提供了一种较为有效的进程同步机制,能够满足读者写者问题的操作需求。
(3)采用不同的优先级设置,可以使读者写者进程之间实现不同的访问策略,进而实现不同的访问效果。
操作系统原理实验报告实验名称: DEBUG命令的使用姓名:学号:班级:计算机指导老师:罗辛一、实验内容(描述实验内容)1、请自学并完成如下内容:(1)DEBUG的使用方法(1)(2)DEBUG的使用方法(2)2、用DEBUG调试、运行可执行程序。
1)进入DEBUG后,首先用命令R查看当前DS和IP寄存器内容,记录此值。
2)学习R,D,A,U,T,P,G命令的使用。
3)用命令A汇编下列指令,并判断指令正误并说明原因。
(1)LEA DI,[AX](2)MOV DS,2010(3)PUSH AL(4)MOV [BX],03.用A命令汇编下列程序段,完成将DS:2000开始的5个字节内存内容相加,并把相加的结果存放在DS:2005内存单元中,将程序写到硬盘上,然后用DEBUG调试﹑运行该程序,查看运行结果,观察程序段能否完成指定功能,若不能,说明原因。
二、实验目的(描述实验目的)1.学习使用DEBUG程序的各种命令。
2.掌握用DEBUG调试自编程序的方法,为以后实验打下基础。
三、实验原理(描述实验基本原理)DEBUG的使用四、实验过程(重点部分,必须包括:实验开发环境、实验步骤、实验源程序代码及其结构分析)环境:windows步骤:1.自学DEBUG的使用2. 用DEBUG调试、运行可执行程序(1)LEA DI,[AX](2)MOV DS,2010(3)PUSH AL(4)MOV [BX],052000五、实验结果(把程序运行的结果通过截屏帖出来,并简单描述每个截图的意思)(1)用r命令查看寄存器内容DS=13E1, IP=0100 (2)各种命令的使用(3)指令均错误1、AX不能用作寄存器间接寻址2、DS不能作为目的操作数3、AL不能使用PUSH4、立即数不能赋给地址单元3思考题:1.指令MOV [BX],AX中,操作数[BX]的寻址方式是什么?在DEBUG下执行完该指令后,如何查看执行结果?寄存器间接寻址方式运用r命令查看2.可否随意在DEBUG提示符“-”后不带参数发出命令G?什么情况下使用命令G时,可不用“=”给出执行首地址?可以已知想开始的位置就是当前地址时,同时在所运行的程序中有结束或返回指令六、实验心得体会(写出在做实验过程中碰到的问题、解决方法、存在的不足,实验过程中所获得的经验等等)虽然在阅读学习时遇到了一些不懂的地方,但在自己的思考与实践下,对debug 有了一定的了解与领悟七、参考文献。
读者-写者实验报告
姓名:何绍金
班级:自动化1202
学号:201203870408
指导教师:张健
2014年11月11日
一.实验题目
经典的同步问题——读者-写者问题。
二. 实验内容
1.实验要求
(1)允许多个读者同时执行读操作;
(2)不允许读者、写者同时操作;
(3)不允许多个写者同时操作。
2.测试数据文件:
1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5
5 W 5.1 3
注意:在创建数据文件时,要求在记事本中手工逐个键入数据。
三.实验流程图
实验流程图附在页末。
四.实验小结
通过本次的实验设计,把教材中的理论知识转化为实践,在一定程度上加深了我对读者-写者这类经典的同步问题的理解,同时也提高了我的动手编程和独立思考的能力。
虽然在分析问题的过程中,遇到了很多的疑惑与不解,但同时掌握了很多进程同步的知识。
东华大学计算机学院操作系统实验报告实验名称:读者写者问题姓名:姜元杰学号:111310228班级:计算机1102指导老师:李继云报告日期:2013/10/12一、实验概述1.实验目标在Windows系统平台下,了解Windows编程基本知识,通过创建线程等一系列操作实现进程同步经典问题——读者写者问题。
2.实验要求在Windows7环境下,创建一个控制台进程,此进程包含n个线程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验内容1.设计思路通过仔细分析问题,实验实现内容分别为读者优先部分与写者优先部分。
通过建立统一的线程数组存储所有待创建线程,并在系统后台分别存于可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
通过程序代码实现读读允许,读写互斥,写写互斥。
对于读者优先部分,引入Mutex信号量和临界区对象RP_Writer实现。
读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_Count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_Count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_Count变量。
因此需要一个互斥对象Mutex来实现对全局变量read_Count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象RP_Writer。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_ Count=l 时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象RP_Writer上。
当写者拥有临界区的所有权时,第一个读者判断完"read_Count==1"后阻塞在write上,其余的读者由于等待对read_Count的判断,阻塞在Mutex上。
对于写者部分,与读者优先类似;不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。
为此应当添加一个整型变量write_Count,用于记录正在等待的写者的数目,当write_Count=0时,才可以释放等待的读者线程队列。
增加一个互斥对象Mutex3,维护对全局变量write_Count的互斥修改。
为了实现写者优先,应当添加一个临界区对象CS_Reader,当有写者在写文件或等待时,读者必须阻塞在CS_Reader上,同时读者线程除了要对全局变量read_Count实现操作上的互斥外,还必须有一个互斥对象对阻塞CS_Reader这一过程实现互斥。
2.主要数据结构int readCount:访问资源的读者线程数目;int writeCount:访问资源的写者线程数目;CRITICAL_SECTION RP_Writer:临界区对象,读者优先中用于阻塞写者;CRITICAL_SECTION CS_Writer:临界区对象,写者优先中实现写写互斥;CRITICAL_SECTION CS_Reader:临界区对象,写者优先中用于阻塞读者,体现写者优先struct Thread :线程信息结构体结构表示,成员变量包括int Number , char Type ,double RunTime, WaitTime ,分别代表线程序号,线程种类(读者或写者),等待时间,作业时间。
HANDLE Mutex1:互斥信号量,用于实现写者优先。
HANDLE Mutex2:互斥信号量,用于维护read_Count 修改。
HANDLE Mutex3:互斥信号量,用于维护write_Count 修改。
3. 主要代码结构int main() \\main 函数菜单界面 void ReaderPriority(char *file) \\读者优先主控程序 void RP_ReaderThread(void *p) \\读者优先-读者线程 void RP_WriterThread(void *p) \\读者优先-写者线程 void WriterPriority(char *file) \\写者优先主控程序 void WP_ReaderThread(void *p) \\写者优先-读者线程 void WP_WriterThread(void *p) \\写者优先-写者线程4. 主要代码段分析a) 创建文件输入流inFile 读入文件int main()RP_ReaderThread RP_WriterThread WP_ReaderThread WP_WriterThreadReaderPriority WritePriority2.读者优先读者线程部分:WaitForMutex = WaitForSingleObject(Mutex, -1);// P(h_mutex)readCount++;if(readCount == 1)// 读者线程进入临界区,实现读者优先{EnterCriticalSection(&RP_Writer);}ReleaseMutex(Mutex);// V(h_mutex)printf("Reader thread %d begins to read file.\n",Number);// 读者线程开始作业Sleep(RunTime);// 作业时间printf("Reader thread %d finished reading file.\n",Number);// 作业完成WaitForMutex=WaitForSingleObject(Mutex,-1);// P(h_mutex) 读者线程对象已触发readCount--;// 读者线程退出if(readCount == 0)// 所有读者线程都已作业完毕,释放临界区对象,写者可作业{LeaveCriticalSection(&RP_Writer);}ReleaseMutex(Mutex);// V(h_mutex)3.写者优先写者线程部分:printf ("Writer thread %d sents the reading require.\n", Number);// 读者线程从创建m_delay秒后,发送读申请WaitForMutex3 = WaitForSingleObject(Mutex3, -1);// P(Mutex3) 维护writeCount修改// P(h_mutex)writeCount++;if(writeCount == 1)// 临界区有写者线程作业时,阻塞一切读者线程{EnterCriticalSection(&CS_Reader);}ReleaseMutex(Mutex3);// V(Mutex3)EnterCriticalSection(&CS_Writer);// 写写互斥printf("Writer thread %d begin to write the file.\n",Number);Sleep(RunTime);printf("writer thread %d finishing writing file.\n",Number);LeaveCriticalSection(&CS_Writer);WaitForMutex3 = WaitForSingleObject(Mutex3,-1);// 维护writeCount修改writeCount--;if(writeCount==0)// 当所有写者线程作业完毕,释放读者线程临界区对象{LeaveCriticalSection(&CS_Reader);}ReleaseMutex(Mutex3);// V(Mutex3)三、实验结果1.基本数据基本数据:TestData.dat(见附件)数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,各个字段间用空格分隔。
第一字段为一个正整数,表示线程序号。
第二字段表示相应线程角色,R表示读者,w表示写者。
第三字段为一个正数,表示读写操作的开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第四字段为一个正数,表示读写操作的持续时间。
当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
数据文件内容:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 32.源代码行数:代码共303行。
3.完成实验投入时间:累计共7小时4.讨论次数:3次5.测试数据分析:分析详情见1.基本数据6.测试结果分析:程序菜单界面:1)读者优先:读者优先结果分析:根据测试数据及读者优先原则可知,线程1R在第3s先执行,当它执行1s后,线程2W发出申请,但被阻塞,实现读写互斥。
然后线程3R,线程4R在第5、6s时发出申请并被准许访问数据区,实现了多个读者同时读数据允许。
而在5.1s发出写申请的线程5W则被阻塞。
当读者线程根据时间都完成后,写者线程2W先被唤醒,并且在它完成之前,写者线程5W仍然是阻塞状态,从而实现了写写互斥。
2)写者分析:写者优先结果分析:根据测试数据及写者优先原则可知,线程1R在第3s先执行,当它执行1s后,线程2W发出申请,但被阻塞,实现读写互斥。
然后线程3R、线程5W、线程4R在第5s、5.1s、6s时发出申请,均被阻塞。