乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      哈工大操作系統(tǒng)實(shí)驗---lab8:proc文件的實(shí)現(xiàn)

       印度阿三17 2019-06-28

      實(shí)驗內(nèi)容

      在Linux0.11上實(shí)現(xiàn)procfs(proc文件系統(tǒng))內(nèi)的psinfo節(jié)點(diǎn),當(dāng)讀取此節(jié)點(diǎn)的內(nèi)容的時候,可得到系統(tǒng)當(dāng)前所有進(jìn)程的狀態(tài)信息,例如,用cat命令顯示/proc/procfo的內(nèi)容,可得到:

      # cat /proc/psinfo
       pid    state    father    counter    start_time
       0    	1    	-1    		0     	  0
       1    	1    	 0    		28        1
       4    	1    	 1    		1    	  73
       3    	1    	 1    		27        63
       6    	0   	 4    		12        817
      
      # cat /proc/hdinfo 
      total_blocks:    62000;
      free_blocks:     39037;
      used_blocks:     22963;

      procfs及其節(jié)點(diǎn)要在內(nèi)核啟動時自動創(chuàng)建,相關(guān)功能的實(shí)現(xiàn)放在fs/proc.c文件。


      實(shí)驗過程

      • 第一步: 增加新文件類型,在include/sys/stat.h文件中定義了幾種文件類型和相應(yīng)的測試宏:

      //已有的宏定義
      #define S_IFMT 00170000 //文件類型(都是8進(jìn)制表示)
      #define S_IFREG 0100000	//普通文件
      #define S_IFCHAR 0020000 //字符設(shè)備文件
      #define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG) //測試m是否是普通文件
      #define S_ISCHAR(m) (((m) & S_IFMT) == S_IFCHAR) //測試m是否是字符設(shè)備文件
      //proc文件的宏定義/宏函數(shù)
      #define S_IFPROC 0030000
      #define S_ISPROC(m) (((m) & S_IFMT) ==  S_IFPROC) //測試m是否是proc文件

      在這里插入圖片描述

      • 第二步: 讓mknod()支持新的文件類型,文件/proc/psinfo以及/proc/hdinfo索引節(jié)點(diǎn)需要通過mknod()系統(tǒng)調(diào)用建立,所以要讓它支持新的文件類型,直接修改fs/namei.c文件中的sys_mknod()函數(shù)的代碼,在其中增加關(guān)于proc文件系統(tǒng)的判斷:

      if(S_ISBLK(mode) || S_ISCHAR(mode) || S_ISPROC(mode))
      	inode->izone[0] = dev;

      在這里插入圖片描述

      • 第三步: 進(jìn)程proc文件初始化,可以在系統(tǒng)啟動時就建立那些proc文件系統(tǒng)(根目錄/proc)下的proc文件(其下的子文件/proc/psinfo、/proc/hdinfo),通常Linux操作系統(tǒng)也都是在系統(tǒng)啟動以后就直接創(chuàng)建那些proc文件的,顯然要修改系統(tǒng)啟動時的調(diào)用的main(),因為是要創(chuàng)建文件,所以當(dāng)然應(yīng)該在文件系統(tǒng)已經(jīng)掛載以后才可以操作,在main()的最后會從內(nèi)核態(tài)切換到用戶態(tài),并調(diào)用init(),而init()要做的第一件事就是掛載根文件系統(tǒng):

      void init(void)
      {
      	setup((void *) &drive_info);
      }

      顯然在執(zhí)行setup((void *) &drive_info)的時候,也就是根文件系統(tǒng)掛載以后就可以創(chuàng)建proc文件了,首先建立/proc目錄,然后再建立該目錄下的各個proc文件節(jié)點(diǎn),建立目錄用mkdir(),建立文件用mknod()。
      現(xiàn)在可以調(diào)用mkdir()來創(chuàng)建proc目錄,調(diào)用mknod()來創(chuàng)建proc目錄下的各個proc文件節(jié)點(diǎn)了。
      內(nèi)核初始化的全部工作是在main()中完成,而/init/main()在最后從內(nèi)核態(tài)切換到用戶態(tài),并調(diào)用init()。init()做的第一件事情就是掛載根文件系統(tǒng):setup((void *) &drive_info);

      procfs的初始化工作應(yīng)該在根文件系統(tǒng)掛載之后開始。它包括兩個步驟:

      • 建立/proc目錄

      • 建立/proc目錄下的各個結(jié)點(diǎn)

      建立目錄和結(jié)點(diǎn)分別需要調(diào)用mkdir()和mknod()系統(tǒng)調(diào)用。因為初始化時已經(jīng)在用戶態(tài),所以不能直接調(diào)用sys_mkdir()和sys_mknod()。必須在初始化代碼所在文件中實(shí)現(xiàn)這兩個系統(tǒng)調(diào)用的用戶態(tài)接口,即API

      _syscall2(int,mkdir,const char*,name,mode_t,mode)
      _syscall3(int,mknod,const char *,filename,mode_t,mode,dev_t,dev)

      在這里插入圖片描述
      在這里插入圖片描述
      mkdir()mode參數(shù)的值可以是“0755”(rwxr-xr-x),表示只允許root用戶改寫此目錄,其它人只能進(jìn)入和讀取此目錄。
      procfs是一個只讀文件系統(tǒng),所以用mknod()建立psinfo結(jié)點(diǎn)時,必須通過mode參數(shù)將其設(shè)為只讀。建議使用“S_IFPROC|0444”做為mode值,表示這是一個proc文件,權(quán)限為0444(r--r--r--),對所有用戶只讀。
      mknod()的第三個參數(shù)dev用來說明結(jié)點(diǎn)所代表的設(shè)備編號。對于procfs來說,此編號可以完全自定義。proc文件的處理函數(shù)將通過這個編號決定對應(yīng)文件包含的信息是什么。例如,可以把0對應(yīng)psinfo,1對應(yīng)hdinfo,2對應(yīng)inodeinfo。
      上述步驟完成以后,就可以使用make all編譯內(nèi)核,然后./run運(yùn)行內(nèi)核,使用ll /proc可以看到:

      在這里插入圖片描述

      inode->i_mode就是通過mknod()設(shè)置的mode。信息中的XXX和你設(shè)置的S_IFPROC有關(guān)。通過此值可以了解mknod()工作是否正常。這些信息說明內(nèi)核在對psinfo進(jìn)行讀操作時不能正確處理,向cat返回了EINVAL錯誤。因為還沒有實(shí)現(xiàn)處理函數(shù),所以這是很正常的。

      注意:博主在此沒截使用cat命令的圖片,但是就是這個么道理,嘻嘻。

      這些信息至少說明,psinfo被正確open()了。所以我們不需要對sys_open()動任何手腳,唯一要打補(bǔ)丁的,是sys_read()

      • 第四步: 讓proc文件(psinfo、hdinfo、inodeinfo)可讀
        open()沒有問題,那么需要修改的就是sys_read()了。
        首先在fs/read_write.c中添加extern,表示proc_read函數(shù)是從外部調(diào)用的。

      在.c文件中要引入另一個文件,而且是另一個.c文件的全局變量或者函數(shù),就需要用extern來說明一下。

      在這里插入圖片描述
      然后仿照其他if語句,添加proc文件的proc_read()調(diào)用。
      在這里插入圖片描述

      • 第五步: 實(shí)現(xiàn)上述的proc_read()函數(shù),用于讀取proc文件內(nèi)容,實(shí)現(xiàn)在fs/proc.c文件下。
        在這里插入圖片描述

      #include <linux/sched.h>
      #include <linux/kernel.h>
      #include <asm/segment.h>
      #include <stdarg.h>
      #include <stddef.h>
      
      extern int vsprintf(char * buf, const char * fmt, va_list args);
      
      //Linux0.11沒有sprintf(),該函數(shù)是用于輸出結(jié)果到字符串中的,所以就實(shí)現(xiàn)一個,這里是通過vsprintf()實(shí)現(xiàn)的。
      int sprintf(char *buf, const char *fmt, ...){
          va_list args; int i;
          va_start(args, fmt);
          i=vsprintf(buf, fmt, args);
          va_end(args);
          return i;
      }
      
      int proc_read(int dev, char * buf, int count, unsigned long * pos){
          struct task_struct ** p;
          int output_count=0;
          char * proc_buf=NULL;
          int file_size=0;
          int offset=*pos;
      
          struct super_block * sb; 
          struct buffer_head * bh;
          int total_blocks, total_inodes;
          int used_blocks=0, free_blocks=0;
          int i,j,k;
          char * db=NULL;
      
      	//硬盤總共有多少塊(空閑   非空閑),有多少inode索引節(jié)點(diǎn)等信息都放在super塊中。
          sb=get_super(current->root->i_dev);
          total_blocks = sb->s_nzones;
          total_inodes=sb->s_ninodes;
      	s_imap_blocks = sb->s_imap_blocks;
      	s_zmap_blocks = sb->s_zmap_blocks;
      
      	//psinfo: 對應(yīng)的就是輸出系統(tǒng)此時的全部進(jìn)程的狀態(tài)信息
          if(dev==0)
          { 
              proc_buf=(char *)malloc(sizeof(char *)*1024);
              file_size=sprintf(proc_buf,"pid\tstate\tfather\tcounter\tstart_time\n");
      
      		//這里借鑒了,進(jìn)程切換函數(shù)schedule()的代碼,也就是遍歷系統(tǒng)全部的進(jìn)程。
              for(p = &LAST_TASK ; p >= &FIRST_TASK ; --p)
                  if(*p)
                      file_size =sprintf(proc_buf file_size,"%d\t%d\t%d\t%d\t%d\n",(*p)->pid,(*p)->state,(*p)->father,(*p)->counter,(*p)->start_time);
      
              *(proc_buf file_size)='\0';
          }
      
      	//hdinfo: 打印出硬盤的一些信息,
      	//s_imap_blocks、ns_zmap_blocks、
      	//total_blocks、free_blocks、used_blocks、total_inodes
          if(dev==1) 
          {
              for(i=0;i<sb->s_zmap_blocks;i  )
              {
                  bh=sb->s_zmap[i];
                  db=(char*)bh->b_data;
                  for(j=0;j<1024;j  ){
                      for(k=1;k<=8;k  ){
                              if((used_blocks free_blocks)>=total_blocks)
                                  break;
                              if( *(db j) & k)
                                  used_blocks  ;
                              else
                                  free_blocks  ;
                      }
                  }
              }
      
              proc_buf=(char*)malloc(sizeof(char*)*512);
              file_size=sprintf(proc_buf,"s_imap_blocks:%d\ns_zmap_blocks:%d\n",s_imap_blocks,s_zmap_blocks);
              file_size =sprintf(proc_buf file_size,"total_blocks:%d\nfree_blcoks:%d\nused_blocks:%d\ntotal_indoes:%d\n",total_blocks,free_blocks,used_blocks,total_inodes);
          }
      
      	//將proc_buf緩沖區(qū)的內(nèi)容放入文件
          while(count>0)
              if(offset>file_size)
                  break;
              put_fs_byte(*(proc_buf offset),buf  );
              offset  ;
              output_count  ;
              count--;
          }
      
      	//重置文件的pos位置,也就是指向文件末尾的指針
          (*pos) =output_count; 
      
          free(proc_buf);
          return output_count;
      }

      由于添加了一個文件proc.c,所以需要改下fs/Makefile,
      在這里插入圖片描述
      在這里插入圖片描述

      上述的代碼,是用的這位同學(xué)的,在此表示感謝!
      (但是我搞不清為什么是proc_dev,添加的文件不是proc.c嗎,如果有人可以解答,可以評論下。)

      然后make all編譯內(nèi)核,./run運(yùn)行內(nèi)核,輸出cat命令,即可查看psinfo(當(dāng)前系統(tǒng)進(jìn)程狀態(tài)信息)和hdinfo(硬盤信息)的信息。
      在這里插入圖片描述


      實(shí)驗問題

      • 如果要求你在psinfo之外再實(shí)現(xiàn)另一個結(jié)點(diǎn),具體內(nèi)容自選,那么你會實(shí)現(xiàn)一個給出什么信息的結(jié)點(diǎn)?為什么?

      我會實(shí)現(xiàn)meminfo、cpuinfo這些節(jié)點(diǎn),分別對應(yīng)的信息是系統(tǒng)內(nèi)存信息和cpu的信息,原因是我只知道這兩個名詞了

      • 一次read()未必能讀出所有的數(shù)據(jù),需要繼續(xù)read(),直到把數(shù)據(jù)讀空為止。而數(shù)次read()之間,進(jìn)程的狀態(tài)可能會發(fā)生變化。你認(rèn)為后幾次read()傳給用戶的數(shù)據(jù),應(yīng)該是變化后的,還是變化前的? 如果是變化后的,那么用戶得到的數(shù)據(jù)銜接部分是否會有混亂?如何防止混亂? 如果是變化前的,那么該在什么樣的情況下更新psinfo的內(nèi)容?

      我認(rèn)為后幾次read()傳遞給用戶的數(shù)據(jù)應(yīng)該是變化前的,因為讀完一部分?jǐn)?shù)據(jù)之后,之前讀取的進(jìn)程狀態(tài)信息可能已經(jīng)發(fā)生了改變了,那么讀給proc_buf緩沖區(qū)的內(nèi)容還是讀之前的,所以可能會導(dǎo)致讀到的數(shù)據(jù)出現(xiàn)混亂(數(shù)據(jù)不正確?),要使得數(shù)據(jù)讀的正確、不混亂,就要在讀的時候讓想要變化的進(jìn)程先等待,等讀完了數(shù)據(jù)放到了文件中以后,再喚醒要更新的進(jìn)程。

      注:我的答案很可能不準(zhǔn)確,請別被我誤導(dǎo)了。


      HIT-OS-LAB參考資料:
      1.《操作系統(tǒng)原理、實(shí)現(xiàn)與實(shí)踐》-李治軍、劉宏偉 編著
      2.《Linux內(nèi)核完全注釋》
      3.兩個哈工大同學(xué)的實(shí)驗源碼
      4.Linux-0.11源代碼
      (上述資料,如果有需要的話,請主動聯(lián)系我))

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多