天天看點

[閱讀筆記]fsnotify源碼閱讀

fsnotify的github位址是

<a href="https://github.com/howeyc/fsnotify">https://github.com/howeyc/fsnotify</a>

fsnotify是一個檔案夾監控應用。可以使用建立一個watcher來對某個檔案夾進行監控

檔案目錄很簡單,實際就兩個程式檔案,fsnotify.go 和 各平台的fsnotify_xxx.go

後一個檔案是各個不同平台的實作

example_test.go中給的是最簡單的實際應用

先fsnotify.newwatcher()

再開一個goroutine監聽檔案夾修改的事件

然後使用watcher.watch()來監聽一個檔案夾

fsnotify中的幾個public函數watch,watchflags,removewatch是對watcher的具體封裝,函數名一看就明白了什麼意思。

這裡的flag标志watcher要監聽檔案夾的哪些事件,watch預設監聽所有事件。

string函數能用string表示出事件。這裡學了一招使用events = events[1:] 來達到trim同樣的目的。

purgeevents是将内部事件轉成外部事件。這個内部事件指的是syscall包有的對事件的封裝和标志位,外部事件指fsnotify對事件的再次封裝

下面就到fsnotify_linux.go看linux平台下的實作。

fileevent類型:

mask,代表事件的掩碼,這裡的事件碼對應的實際上是syscall包中constants對應的一些位置碼

cookie,每個事件會配置設定一個唯一的cookie,這個具體是什麼也不了解

name,觸發事件的檔案名

下面是一個watch類型

wd,syscall中對檔案監控傳回的watch id

flags,syscall中對檔案的flag

watcher結構:

mu:互斥鎖,控制并發,對watcher要進行互斥監控

fd:watcher的檔案描述符,不要把這個了解成監控的檔案的檔案描述符。了解成通知watch消息的檔案描述符

watches:要監控的檔案夾路徑和watch結構的映射

fsnflags:要監控的事件标志位

paths:要監控watch id和檔案夾路徑的映射,上面三個其實和起來就能完成了path和watch的互相查找

error:如果發生錯誤,從這個channel将錯誤通知主go routine

internalevent:檔案事件隊列,内部的檔案事件就放在這個隊列中

event:已經處理的檔案事件隊列

done:主goroutine監聽是否已經結束的通知通道

isclose:是否已經結束的标志位,當然隻能自身的goroutine使用

下面看newwatcher這個函數

這裡調用了syscall的inotifyinit來進行初始化

學了一點,當syscall出現錯誤的時候,可以使用os.newsyscallerror來抛出錯誤

裡面起了兩個goroutine

readevents()和purgeevents()

purgeevents()上面已經有了,下面是readevents

先從w.fd中擷取出syscall.inotifyevent,這個是syscall包的通知事件。這個事件是怎麼被塞入這個fd的呢?是syscall的syscall.inotifyaddwatch之後如果檔案有修改就會将event寫入到這個fd中。這個fd就相當于是一個先進先出的隊列了。

讀出initofifyevent之後就需要将它變成我們這個包中定義的fileevent。并将這個event放入到internalevent中去。這裡隻是捕獲消息,并沒有對消息進行過濾之類的操作。考慮是否彈出和是否傳回是在purgeevent中進行過濾。

對readevents讀完之後其他的就很好了解了。

addwatch就是調用了一下syscall.inotifyaddwatch

removewatch就是調用了一下syscall.inotifyrmwatch 

繼續閱讀