In xnu haben wir die Entität vnode_t
, die die Datei global darstellt.vnode und Dateideskriptor in xnu, wo wird der Dateioperationsvektor gespeichert
Jeder Prozess kann auf die Datei zugreifen (vorausgesetzt, es richtig Berechtigungen), indem Sie neuen Dateideskriptor und stellen Sie den V-Knoten unter fg_data
fp->f_fglob->fg_data = vp;
den V-Knoten enthält eine Liste von grundlegenden Aktionen für alle relevanten Vorgänge und gesetzt in Übereinstimmung mit dem FS der Datei. h., der HFS + -Treiber implementiert einen solchen Vektor und setzt seinen V-Knoten entsprechend.
int (**v_op)(void *); /* vnode operations vector */
Dies ist ein Vektor für Funktionszeiger für alle Aktionen, die auf dem Vnode ausgeführt werden können.
Darüber hinaus haben wir die FileOps Struktur, die Teil der Dateideskriptor (fg_global), die beschreiben, eine minimale Teilmenge dieser Funktionen ist:
Hier ist eine typische Definition:
const struct fileops vnops = {
.fo_type = DTYPE_VNODE,
.fo_read = vn_read,
.fo_write = vn_write,
.fo_ioctl = vn_ioctl,
.fo_select = vn_select,
.fo_close = vn_closefile,
.fo_kqfilter = vn_kqfilt_add,
.fo_drain = NULL,
};
und wir legen sie es hier:
fp->f_fglob->fg_ops = &vnops;
ich sah, dass, wenn reguläre Datei unter lokalem Dateisystem (HFS +) zu lesen, ist es die file_descriptor und nicht der V-Knoten ... wirkt durch
* frame #0: 0xffffff801313c67c kernel`vn_read(fp=0xffffff801f004d98, uio=0xffffff807240be70, flags=0, ctx=0xffffff807240bf10) at vfs_vnops.c:978 [opt]
frame #1: 0xffffff801339cc1a kernel`dofileread [inlined] fo_read(fp=0xffffff801f004d98, uio=0xffffff807240be70, flags=0, ctx=0xffffff807240bf10) at kern_descrip.c:5832 [opt]
frame #2: 0xffffff801339cbff kernel`dofileread(ctx=0xffffff807240bf10, fp=0xffffff801f004d98, bufp=140222138463456, nbyte=282, offset=<unavailable>, flags=<unavailable>, retval=<unavailable>) at sys_generic.c:365 [opt]
frame #3: 0xffffff801339c983 kernel`read_nocancel(p=0xffffff801a597658, uap=0xffffff801a553cc0, retval=<unavailable>) at sys_generic.c:215 [opt]
frame #4: 0xffffff8013425695 kernel`unix_syscall64(state=<unavailable>) at systemcalls.c:376 [opt]
frame #5: 0xffffff8012e9dd46 kernel`hndl_unix_scall64 + 22
Meine Frage ist, warum ist diese Dualität benötigt, und in welchen Fällen die Operation funktioniert durch die file_descriptor Vektor (fg_ops) und welche Fälle die Operation funktioniert durch den V-Knoten-Vektor (VP-> v_op).
dank
Hallo und danke. nur noch eine Sache. Im Anschluss an Ihre Antwort habe ich weitere Untersuchungen durchgeführt und herausgefunden, dass VNOP_READ 'hfs_vop_read' aufruft, was Teil des HFS + -Treibers ist, der selbst die Cluster-Methode' cluster_read' aufruft, die tatsächlich alle Low-Level-Lesevorgänge (aus dem Cache) ausführt oder von der Platte) .. so weit so gut, aber ich konnte das Synonym in 'mmap' nicht finden, das VNOP_MMAP aufruft, das' hfs_vnop_mmap' aufruft, aber in dieser Funktion, die ENOTSUP zurückgibt "weil wir den Cluster-Layer wollen eigentlich die ganze echte Arbeit machen. " (zitiert aus ihrem Kommentar) ... – osxUser
Dies lässt mich mit der Frage, wer für das Lesen der Datei in mmap Fall verantwortlich ist. Natürlich ist es die Cluster-Schicht, aber wer ruft 'cluster_read' oder etwas Ähnliches aus der mmap Call Trace? – osxUser