1. 程式人生 > 實用技巧 >CS110作業系統原理學習筆記(一)

CS110作業系統原理學習筆記(一)

本篇筆記主要涵蓋CS110第1到第4節課。課程主要是繼續UNIX6,所以新的vfs的那些東西沒有涉及

https://www.youtube.com/watch?v=_LFGjZ0Sc6I&list=PLai-xIlqf4JmTNR9aPCwIAOySs1GOm8sQ

Lecture 1

  • umask, open, read和write系統呼叫
  • touch實現
  • copy實現

1.umask和open系統呼叫

1.1.umask

https://man7.org/linux/man-pages/man2/umask.2.html

umask是一個根據掩碼判斷檔案許可權的命令,也可以用作系統呼叫來設定新檔案建立時候的許可權。

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

mode_t umask(mode_t mask); // mode_t -> Uint32

mode_t old_mask = umask(0); // umask設為0,返回的是原先的umask

第一個是d則表示是資料夾

drwx------ 2 vivek vivek 4096 2011-03-04 02:05 dir1
-rw------- 1 vivek vivek    0 2011-03-04 02:05 file

1.2.open

https://man7.org/linux/man-pages/man2/open.2.html

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); // mode控制權限

flags用bitset控制, 必須包含下面三個中的一個讀寫申明

  • O_RDONLY // 只讀
  • O_WRONLY // 只寫
  • O_RDWR // 可讀可寫

處理方法(用||做or的bitset)

  • O_CREAT 如果檔案不存在,新建一個
  • O_EXCL 如果檔案存在,報錯(寫的時候才用)
    (寫入方法)
  • O_APPEND 用O_APPEND就是在檔案尾繼續寫
  • O_TRUNC 抹除檔案內容,再寫

可處理方法和寫入方法可一起用 O_CREAT|O_WRONLY|O_TRUNC, O_CREAT|O_WRONLY| O_EXCL

1.3.read

read 會嘗試從檔案描述符中讀取count大小的bytes,並放到buffer中(starting at buf)。返回值為成功讀取的bytes,如果0表示讀完了,-1表示異常(檔案位置改變...)。

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

1.4.write

從buf指向的位置開始寫入count個bytes到檔案描述符fd中。 返回值為成功寫入的bytes的數量,0表示沒東西可寫,-1表示異常。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

2.簡單的touch實現

errno是c的一個全域性變數用來儲存程式的異常, errno -l查詢錯誤碼對應的異常。

#include <stdio.h>
#include <fcntl.h> // for open
#include <unistd.h> // for read, open, write
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

const char *kFilename = "my_file";
const int kFileExistsErr = 17;

int main() {
	umask(0); // 重置預設umask再修改umask
	int file_descriptor = open(kFilename, O_WRONLY | O_CREAT | O_EXCL, 0644); 
	if (file_descriptor == -1) {
		printf("There was a problem creating '%s'!\n", kFilename);
		if (errno == kFileExistsErr) {
			printf("The file already exist!\n");
		} else {
			printf("Unknown errono: %d\n", errno);
		}
		return -1;
	}
	close(file_descriptor);
	return 0;
}

許可權也為0644

3.簡單的cp實現

The read system call will block until the requested number of bytes have been read. If the return value is 0, there are no more bytes to read (e.g., the file has reached the end, or been closed).
If write returns a value less than count, it means that the system couldn't write all the bytes at once. This is why the while loop is necessary, and the reason for keeping track of bytesWritten and bytesRead.
You should close files when you are done using them, although they will get closed by the OS when your program ends. We will use valgrind to check if your files are being closed.

read會堵塞

#include <stdio.h>
#include <fcntl.h> // for open
#include <unistd.h> // for read, open, write
#include <stdbool.h>
#include <errno.h>

static const int kWrongArgumentCount = 1;
static const int kSourceFileNonExistent = 2;
static const int kDestinationFileOpenFailure = 4;
static const int kReadFailure = 8;
static const int kWriteFailure = 16;
static const int kDefaultPermissions= 0644;

int main(int argc, char *argv[]) {
  if (argc != 3) {
    fprintf(stderr, "%s <source-file> <destination-file>. \n", argv[0]);
    return kWrongArgumentCount;
  }

  int fdin = open(argv[1], O_RDONLY);
  // 只寫,建立+覆蓋
  int fdout = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, 0644);
  char buffer[1024];
  while (true) { // 保證檔案被讀完
    ssize_t bytesRead = read(fdin, buffer, sizeof(buffer));
    if (bytesRead == 0) break; // 讀完了
    size_t bytesWritten = 0;  // 保證readBuffer的寫完
    while (bytesWritten < bytesRead) {
      bytesWritten += write(fdout, buffer + bytesWritten, bytesRead - bytesWritten);
    }
  }
  close(fdin); 
  close(fdout);
  return 0;
}