| 項目 | 日期 | |
|---|---|---|
| * |
Environment
| |
| 1 | Ubuntu 上的 PPPoE 設定 |
2020/05/01
|
| 2 | ssh 公鑰認證登入 |
2015/02/16
|
| 3 | 在 linux 中無法切換身份? (su: Permission denied) |
2017/12/22
|
| 4 | RHEL8 無法安裝套件 No match for argument: xxx |
2022/03/27
|
| 5 | install nfs server@Ubuntu |
2023/11/08
|
| * |
Shell Scripting
| |
| 1 | 使用 sort、join 處理 csv 檔案 |
2015/01/16
|
| 2 | EBCDIC <=> ASCII 間的轉換 |
2015/01/17
|
| * |
C Programming
| |
| 1 | Linux Network Programming - 初體驗 |
2015/05/23
|
| 2 | byte ordering functions |
2015/05/26
|
| 3 | fork Function |
2015/06/06
|
Google Code Prettify
2015年10月25日 星期日
Linux / Unix
2015年7月19日 星期日
NIO.2: POSIX View
POSIX View 無庸置疑,是為 Unix like 作業系統準備的! 來看看程式吧 ~
1 package idv.steven.nio2.metadata; 2 3 import java.io.IOException; 4 import java.nio.file.Files; 5 import java.nio.file.Path; 6 import java.nio.file.Paths; 7 import java.nio.file.attribute.GroupPrincipal; 8 import java.nio.file.attribute.PosixFileAttributeView; 9 import java.nio.file.attribute.PosixFileAttributes; 10 import java.nio.file.attribute.PosixFilePermission; 11 import java.nio.file.attribute.PosixFilePermissions; 12 import static java.nio.file.LinkOption.NOFOLLOW_LINKS; 13 import java.util.Set; 14 15 public class POSIXView { 16 17 public static void main(String[] args) { 18 PosixFileAttributes attr = null; 19 Path path = Paths.get("/home/steven/seal/steven.pub"); 20 21 // read permissions 22 try { 23 attr = Files.readAttributes(path, PosixFileAttributes.class); 24 } catch (IOException e) { 25 System.err.println(e.getMessage()); 26 } 27 28 System.out.println("File owner: " + attr.owner().getName()); 29 System.out.println("File group: " + attr.group().getName()); 30 System.out.println("File permissions: " + attr.permissions().toString()); 31 32 // set permissions 33 Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("rw-r--r--"); 34 try { 35 Files.setPosixFilePermissions(path, permissions); 36 37 GroupPrincipal group = path.getFileSystem(). 38 getUserPrincipalLookupService().lookupPrincipalByGroupName("steven"); 39 Files.getFileAttributeView(path, PosixFileAttributeView.class).setGroup(group); 40 41 GroupPrincipal groupSteven = (GroupPrincipal) Files.getAttribute(path, "posix:group", NOFOLLOW_LINKS); 42 System.out.println(group.getName()); 43 } catch (IOException e) { 44 System.err.println(e); 45 } 46 } 47 }
解釋程式前,先看一下輸出結果 ...
File owner: steven File group: steven File permissions: [OTHERS_READ, OWNER_WRITE, GROUP_WRITE, OWNER_READ, GROUP_READ]
執行後,steven.pub 的權限如下圖:
程式說明如下:
- 22 ~ 30 行: 讀取檔案的權限,包括檔案的擁有者、群組及讀、寫、執行的權限,這裡的 file permissions 不是用 unix 使用者習慣的 664,而是以文字來表示。
- 33 ~ 35 行: 設定檔案的權限,設定後權限改為 644。
- 37 ~ 45 行: 變更檔案所屬的群組,當然啦~ 這個群組要是 OS 中已經存在的,且是目前執行的這支程式的帳號有權限可以變更的。
如果想要在 Unix/Linux 中建立一個目錄,並設定適當的權限,該怎麼做? 如下:
Path newFolder = FileSystems.getDefault().getPath("/home/steven/newFolder");
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
try {
Files.createDirectory(newFolder, attr);
} catch (IOException e) {
System.err.println(e);
}
先使用 PosixFilePermissions 設定好權限,再用 createDirectory 建立目錄。
2015年6月6日 星期六
fork Function
在「Advanced.Programming.in.the.UNIX.Environment, 3rd.Edition」一書中的8.3節 (p. 230),有個小程式,如下,是用來說明 UNIX 環境中,使用 fork 產生子行程 (child process),要注意的一些事,先看一下程式:
1 #include <stdio.h>
2 #include <unistd.h> 3 4 int globvar = 6; 5 char buf[] = "a write to stdout\n"; 6 7 int main(void) { 8 int var; 9 pid_t pid; 10 11 var = 88; 12 if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) 13 printf("write error"); 14 printf("before fork\n"); 15 16 if ((pid = fork()) < 0) { 17 printf("fork error"); 18 } 19 else if (pid == 0) { 20 globvar++; 21 var++; 22 } 23 else { 24 sleep(2); 25 } 26 27 printf("pid = %ld, getpid = %ld, glob = %d, var = %d\n", (long) pid, (long) getpid(), globvar, var); 28 _exit(0); 29 }上面的程式很簡單的利用 fork 產生一個子行程,等待 2 秒後,印出一段訊息,顯示 fork 傳回值、行程的 pid (process id)、全域變數及區域變數,執行結果如下: (我的程式命名為 forEx01.c)
[steven@CentOS7 Debug]$ ./forkEx01
a write to stdout
before fork
pid = 0, getpid = 9214, glob = 7, var = 89
pid = 9214, getpid = 9213, glob = 6, var = 88
[steven@CentOS7 Debug]$
根據上述的執行結果,說明如下:
- fork 函數會產生一個子行程,子行程會執行父行程 (parent process) fork 之後的指令。
- fork 函數在父行程會傳回子行程的 pid,在子行程則傳回 0,子行程如果要得到父行程的 pid,可以透過 getppid 函數得到值。
- 上面程式讓父行程睡 2 秒後再印出結果,所以第一個結果是子程式印出的,第二個結果是父行程印出的,通常確實是會得到如上的結果 (除了 pid、getpid 的值會不同之外),但是,實際上有時會是父行程先印出,因為那個行程先執行,由 OS 決定,這裡父行程睡 2 秒只是增加子行程先執行的機率。
- 上述程式的全域變數 (global variable) 和區域變數 (local variable) 於子行程中都被加 1,但是都沒有影響到父行程的值,這表示不管是全域變數或區域變數,父行程、子行程都不共用!
- 子行程的輸出接在父行程 fork 前已輸出的內容之後,父行程後面的輸出又接在子行程的輸出之後,完全不會互相覆蓋,因為父行程和子行程會共享在 fork 之前已開啟的所有檔案描述符 (file descriptions),也就是說兩個行程會共享這些檔案的檔案指標! 標準輸出是在父行程一開始執行時就被開啟的,所以會被兩個行程共享。
除了上述程式所展現的父行程、子行程關係外,另外針對行程的一些基本觀念整理如下:
- UNIX 系統在系統啟動後,會啟動許多 process 來處理一些系統面的事,其中一個 pid 為 1 的 process 稱為 init process,是負責啟動和關閉系統。
- 程式以 fork 啟動一個或數個子行程,當子行程結束後,父行程要負責將其佔用的資源都回收後,才可真正將其結束,在子行程已經執行完,但是父行程尚未將其資源回收前,這個子行程就稱為 zombie (僵屍)。
- 如果父行程比子行程更早結束,子行程並不會被迫結束,而是會交由 init process 管理,也就是說,子行程的 ppid 會被改為 1,之後子行程結束,其資源會由 init process 進行回收。
訂閱:
文章 (Atom)
