- user EA 只適用於文件或目錄 (ext2~4上建立時須要:
mount -o user_xattr device dir
)- trusted
- system
- security 略
- 文件系統支持ACL須要
mount -o acl
- 簡單來講ACL是對原有文件系統權限的擴展
- 原有文件系統只針對owner,group和other, ACL支持對單獨用戶進行權限設置
- ACL由一系列ACE組成,ACE由三部分組成
- 標記類型
- 標記限定符(可選,通常爲用戶ID或組ID,下圖帶-表示不可選,同時只存在一條此類型)
- 權限集合
- 示例
![]()
- 最小ACL:和普通文件權限集合同樣只包含ACL_XX_OBJ, ACL_OTHER
- 進程具備特權,執行權限須要至少一條ACL匹配纔有,其餘同普通文件權限
- 進程的有效用戶ID(準確是文件ID下面略)匹配文件的屬主,授予ACL_USER_OBJ的ACE指定權限
- 進程的有效用戶ID匹配了一條ACL_USER,授予權限爲ACL_MASK & ACE指定
- 進程組匹配相似(有效組ID和輔助組任意一匹配,只是匹配了ACL_GROUP_ACE後權限須要& ACL_MASK)
- ACL_OTHER 授予的權限
chmod以後ACL_MASK的做用及其餘api調用 略太雜了以後有使用再記吧node
目錄的inode示例 linux
![]()
- inode可能會有多個文件名(多個硬連接),沒法經過描述符找到文件名
- inode僅在同一文件系統中惟一,硬鏈得在同一文件系統
- inode目錄沒法硬鏈
- _POSIX_SYMLOOP_MAX_ 解引用操做限制<limits.h>
- 軟鏈存儲的優化,路徑名小於60時能夠直接存在存data指針的位置
- l開頭的系統調用每每操做的符號連接文件自己(可是文件的目錄若是是軟鏈,則都會解引用)
- 除了sticky設置的目錄下的軟鏈文件(/tmp)進行刪除和重命名的狀況外,文件的操做的權限爲解引用以後的文件權限。
- 硬鏈了一個軟鏈,linux不會解引用,MAC會。
即便全部指向這個inode的硬鏈都解除了,可是又進程持有改文件的描述符(由於能夠經過打開文件的表找到對應的inode),在關閉描述符以前,系統實際不會刪除改文件算法
- tmpfile 的實現大體應該相似
f = open("tmp_file", O_CREATE|O_EXCL) err =unlink("tmp_file") 複製代碼
#include<unistd.h>
int remove(const char *pathname);
// pathname爲文件調用unlink, 不然調用rmdir,均不解引用。
複製代碼
#include<sys/inotify.h>
// return inotify fd
int inotify_init(void);
// return wd; need read privellege on pathname
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
// 刪除fd裏面的wd
int inotify_rm_watch(int fd, uint32_t wd);
複製代碼
fd,wd一對多編程
每次調用read 讀取fd ,若是不傳O_NONBLOCK會阻塞,傳參的話read會馬上失敗並報錯EAGAINapi
struct inotify_event {
int wd;
uint32_t mask;
uint_32 cookie; // cookie for relate events(ex:rename())
uint32_t len; //sizeof name
char name[]; // 監控爲目錄時返回文件名,爲文件返回空,len爲0
}
複製代碼
- 在事件隊列末尾追加一個新事件會和當前對尾比較,若是struct一致,則合併,忽略屢次。
/proc/sys/fs/inotify/
保存inotify的各類限制
- max_queue_events
- max_user_instances
- max_user_watches
信號是事件發生時對進程的通知機制:也叫軟件中斷cookie
信號一般源於內核數據結構
- 硬件發生異常:被0除,內存訪問錯誤等
- 用戶鍵入產生異常特殊字符:Ctrl+c,Ctrl+z
- 軟件事件:CPU時間超時等等
信號的分類函數
- 標準信號(內核像進程通知事件,一般是1-31)
- 實時信號
- 忽略信號
- 殺死進程(非調用exit終止)
- 產生核心轉儲文件並終止
- 中止進程
- 恢復中止
- 採起默認(用於恢復對默認的修改)
- 忽略默認終止信號
- 執行編寫的信號處理程序(如Ctrl+c, 沒法直接設置處理程序殺死進程或產生核心轉儲文件,能夠經過間接調用abort來產生新的信號)
SIGABRT
: 調用abort()
會產生,會殺死進程併產生核心轉儲文件供調試SIGALARM
: 調用alarm()
或setitimer()
設置定時器到時間,內核會產生該信號SIGBUS
: 內存訪問錯誤SICHLD|SIGCLD
: 子進程終止時發給父進程SIGCONT
: 恢復中止進程- .......
SIGTERM
:標準殺死進程信號kill|killall
會發起SIGKILL
: 必殺信號,處理程序沒法將其阻塞,忽略或 捕獲(測試下);kill -9|kill -KILL
會調用
#include<signal.h>
void ( *signal(int sig, void (*handler)(int))) (int);
//成功返回以前的調用函數地址或者SIG_DFL(設爲默認值)或SIF_IGN(忽略),失敗時返回SIG_ERR
//正常開發不要使用signal,兼容性很差
複製代碼
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
static void sigHandler(int sig){
printf("Ouch\n");
}
int main(void){
if (signal(SIGINT, sigHandler)==SIG_ERR){
printf("error");
exit(-1);
}
for (;;){
printf("*****************************");
sleep(3);
}
}
複製代碼
#include<signal.h>
int kill(pid_t pid, int sig);
複製代碼
- pid>0, 發送給pid進程
- pid=0, 發送給同組全部進程
- pid<-1, 發送給pid絕對值進程組內全部進程
- pid=-1 發送給除了init進程和自身以外的全部有權進程
發送的權限測試
- 特權進程能夠發給全部
- root用戶和組運行的init進程,僅接受安裝了處理器函數的信號
- 非特權進程
![]()
- SIGCONT信號忽視用戶ID檢測,非特權進程能夠向會話內任意進程發送這一信號
sig=0,僅報告進程是否存在優化
#include<signal.h>
int raise(int sig);
//單線程下等於
kill(getpid(), sig)
//支持線程系統下
pthread_kill(pthread_self(),sig)
int killgp(pid_t pgrp, int sig);
//等同於
kill(-pgrp, sig)
複製代碼
#include<signal.h>
// 初始化空的set
int sigemptyset(sigset_t *set);
// 初始化包含全部信號(包括實時信號)的set
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int sig);
int sigdelset(sigset_t *set, int sig);
int sigismember(const sigset_t *set, int sig);
複製代碼
#define _GNU_SOURCE
#include<signal.h>
int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);
int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right);
int sigisemptyset(const sigset_t *set);
複製代碼
內核會爲每一個進程維護一個信號掩碼,即一組信號,並阻塞這些信號對進程的傳遞,一直延遲直至解除(每一個線程可單獨控制)
#include<signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *old_set);
// how=SIG_BLOCK, 當前進程和set取並集
// how=SIG_UNBLOCK, 移除set內信號
// how=SIG_SETMASK, 賦值爲set內信號
// oldset不爲空則指向以前的信號掩碼
// set爲空不作改動
複製代碼
#include<signal.h>
#include<stdlib.h>
int main(void){
sigset_t blockSet, prevMask;
sigemptyset(&blockSet);
sigaddset(&blockSet, SIGINT);
if (sigprocmask(SIG_BLOCK, &blockSet, &prevMask)==-1){
exit(-1);
}
if (sigprocmask(SIG_SETMASK, &prevMask, NULL) == -1){
exit(-1);
}
retunn 0;
}
複製代碼
獲取等待信號
#include<signal.h>
int sigpending(sigset_t *set);
// 標準信號同一信號只會記錄一次,實時信號以後會有排隊處理見22章
複製代碼
#include<signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);
//act 新處置的數據結構,爲NULL則忽略,oldact置位將當前處置
struct sigaction{
void (*sa_handler)(int); // 調用函數地址或者SIG_DFL,SIF_IGN, 爲函數地址時sa_mask和sa_flags纔有效
sigset_t sa_mask; //調用函數時可額外阻塞一組信號
int sa_flags; //略....太多標記了
void (*sa_restorer)(void); //系統內部使用,供恢復上下文
}
複製代碼
- 執行處理器程序時,同一信號第二次到達,若是沒有設爲阻塞會忽略,設爲阻塞的話會保留一次
#include<unistd.h>
int pause(void);
// 進程一直中止直到有處理函數的信號,或者一個未處理信號終止進程
複製代碼