73 lines
2.9 KiB
Markdown
73 lines
2.9 KiB
Markdown
```mermaid
|
||
sequenceDiagram
|
||
%%{init: { 'theme': 'default', 'themeVariables': {
|
||
'primaryColor': '#ff0000',
|
||
'nodeTextColor': '#ffffff',
|
||
'edgeLabelBackground': '#f0f0f0'
|
||
}}}%%
|
||
autonumber
|
||
participant Watcher as Демон-наблюдатель
|
||
participant Kernel as Ядро (fanotify)
|
||
participant Editor as Процесс-редактор (PID X)
|
||
participant FS as Файловая система (целевой каталог/файл)
|
||
participant Ep as epoll
|
||
participant Pfd as pidfd(PID X)
|
||
participant Map as Карта соответствий (в памяти)
|
||
participant ChLog as Журнал изменений
|
||
|
||
Note over Watcher: Инициализация
|
||
Watcher->>Kernel: fanotify_init(PRE_CONTENT|NONBLOCK|CLOEXEC, O_RDONLY|O_CLOEXEC|O_LARGEFILE)
|
||
Watcher->>Kernel: fanotify_mark(ADD|ONLYDIR, EVENT_ON_CHILD|(OPEN[_EXEC]_PERM)|OPEN|CLOSE_WRITE, watchDir)
|
||
Watcher->>Ep: add(fanotify_fd, tag=FAN)
|
||
|
||
Note over Editor: Запрос доступа к файлу
|
||
Editor->>FS: open(target, O_RDONLY/O_RDWR/EXEC)
|
||
FS-->>Kernel: системный вызов доступа
|
||
Kernel-->>Watcher: PERM-событие (+fd, mask, pid)
|
||
|
||
Note over Watcher: Сбор контекста
|
||
Watcher->>FS: fstat(fd) → (inode, dev)
|
||
FS-->>Watcher: inode, dev
|
||
Watcher->>Watcher: readlink(/proc/self/fd/FD) → file_path_open
|
||
Watcher->>Watcher: read /proc/PID/{comm,status} → proc_name, RUID, UID(EUID)
|
||
|
||
%% КЛАДЁМ СВЯЗКУ
|
||
Watcher->>Map: PUT key=(PID,inode,dev), val={proc_name,RUID,UID,file_path_open,changed=false}
|
||
Note over Map: Добавлена связка key=(PID,inode,dev)
|
||
|
||
%% pidfd и epoll
|
||
Watcher->>Pfd: pidfd_open(PID, flags=0)
|
||
Pfd-->>Watcher: pidfd
|
||
Watcher->>Ep: add(pidfd, tag=PID, events=IN|HUP|RDHUP|ERR)
|
||
|
||
%% Разрешаем доступ
|
||
Watcher->>Kernel: fanotify_response{fd, FAN_ALLOW}
|
||
Watcher->>FS: close(fd)
|
||
|
||
Note over Editor: Работа с файлом
|
||
Editor->>FS: write(...)
|
||
Editor->>FS: close()
|
||
Kernel-->>Watcher: CLOSE_WRITE (+fd)
|
||
|
||
Note over Watcher: Фиксация факта изменения
|
||
Watcher->>FS: fstat(fd) → (inode, dev)
|
||
FS-->>Watcher: inode, dev
|
||
Watcher->>Map: GET key=(PID,inode,dev)
|
||
Map-->>Watcher: {…}
|
||
Watcher->>Map: SET changed=true
|
||
Watcher->>FS: close(fd)
|
||
|
||
Note over Editor: Завершение процесса
|
||
Editor->>Editor: exit()
|
||
Pfd-->>Ep: EPOLLIN/HUP (pid завершён)
|
||
Ep-->>Watcher: событие(tag=PID)
|
||
|
||
%% ПИШЕМ ЖУРНАЛ И ЧИСТИМ
|
||
Watcher->>Map: GET_ALL where pid=PID
|
||
Map-->>Watcher: список записей
|
||
Watcher->>ChLog: APPEND для всех changed=true → {proc=proc_name, file=file_path_open, uid=UID, ruid=RUID}
|
||
Watcher->>Ep: remove(pidfd)
|
||
Watcher->>Pfd: close(pidfd)
|
||
Watcher->>Map: DELETE_ALL where pid=PID
|
||
Note over Map: Удалены все связки для PID
|
||
```
|