  Linux Kernel 2.4 Internals
  Tigran Aivazian tigran@veritas.com
  7 August 2002 (29 av 6001)
  : Hiroshi Miura miura@da-cha.org
  22 May 2003

  ̕Linux 2.4J[l̎łB̍ŐVł́AȉURL
  _E[hł܂B <http://www.moses.uklinux.net/patches/lki.sgml>
  ܂A󕶂̍ŐVł́A <http://www.da-cha.org/> ɂĔzz܂B
  KCh́A݂ł́ALDP (Linux Documentation Project)̈ꕔƂȂĂ
  A <http://www.linuxdoc.org/guides.html> lXȃtH[}bgŃ_
  E[hł܂B܂AŐVł
  <http://www.moses.uklinux.net/patches/lki.html>ICœǂނ
  Ƃł܂B This documentation is free software; you can redis-
  tribute it and/or modify it under the terms of the GNU General Public
  License as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.  
  ́AVERITAS\tgEGAЂŁAVjALinuxJ[lGWjAƂē
  ܂BĂ̖{́AVERITASŁÃ^CgōsĂZ
  ̃g[jOR[X/u`̕⏕̂߂ɏ̂łBӎ: Juan
  J. Quintela (quintela@fi.udc.es), Francis Galiegue (fg@mandrake-
  soft.com), Hakjun Mun (juniorm@orgio.net), Matt Kraai
  (kraai@alumni.carnegiemellon.edu), Nicholas Dronen (ndronen@frii.com),
  Samuel S Chessman (chessman@tux.org), Nadeem Hasan (nhasan@nadmm.com),
  Michael Svetlik (m.svetlik@ssi-schaefer-peem.com) ݂̂Ȃ܂ɂ́A
  ̒ƁAӌ܂B Linux y[WLbV̏
  ́AChristoph Hellwig (hch@caldera.de) ɂďꂽ̂łB IPC
  @\̏͂́ARussell Weight (weightr@us.ibm.com)  Mingming Cao
  (mcao@us.ibm.com) ɂ菑ꂽ̂łB IPC@\̏͂́A Russell
  Weight (weightr@us.ibm.com) and Mingming Cao (mcao@us.ibm.com) 菑
  ꂽ̂łB{́AOYLu(miura@da-cha.org)҂̋𓾂Ė
  ôłBoɂĂ̎wÉAOY܂ł肢܂Boɂ
  ẮAсls(zap03216@nifty.ne.jp)A
  (noboru@ylug.org)MdȂwEƒ܂B肪Ƃ
  ܂B
  ______________________________________________________________________

  ڎ

  1. u[g
     1.1 LinuxJ[lC[W̍쐬
     1.2 u[g: T_
     1.3 u[g: BIOS POST
     1.4 u[g: u[gZN^ setup
     1.5 LILOu[g[_ƂĎg
     1.6 x̏
     1.7 x86łSMPu[g
     1.8 f[^уR[h̉
     1.9 J[lR}hC

  2. vZXƊ荞݊Ǘ
     2.1 ^XN\̂ƃvZXe[u
     2.2 ^XNƃJ[lXbh̐ƏI[
     2.3 LinuxXPW[
     2.4 Linuxł̃NXg̎
     2.5 EGCgL[
     2.6 J[l^C}
     2.7 {gn[t
     2.8 ^XNL[
     2.9 ^XNbg
     2.10 \tg荞
     2.11 VXeR[i386ł͂ǂ̂悤ɎĂ邩?
     2.12 Ag~bNȑ
     2.13 XsbNAǂݏXsbNArbO[_[XsbN
     2.14 Z}tHƓǂݏZ}tH
     2.15 W[ǂݍ݂̃J[lT|[g

  3. zt@CVXe (VFS)
     3.1 Inode LbVDcache Ƃ̑ݍp
     3.2 t@CVXeo^/o^
     3.3 t@CfXNv^Ǘ
     3.4 t@C\̊Ǘ
     3.5 X[p[ubNƃ}Eg|CgǗ
     3.6 zt@CVXe̗: pipefs
     3.7 fBXNt@CVXe̗:BFS
     3.8 shCƃoCitH[}bg

  4. Linux y[WLbV
  5. IPC@\
     5.1 Z}tH
        5.1.1 Z}tHVXeR[̃C^[tF[X
           5.1.1.1 sys_semget()
           5.1.1.2 sys_semctl()
           5.1.1.3 sys_semop()
              5.1.1.3.1 ubNZ}tH
              5.1.1.3.2 Z}tH̎s
              5.1.1.3.3 ubLOZ}tH
        5.1.2 Z}tHƎɃT|[g\
           5.1.2.1 struct sem_array
           5.1.2.2 struct sem
           5.1.2.3 struct seminfo
           5.1.2.4 struct semid64_ds
           5.1.2.5 struct sem_queue
           5.1.2.6 struct sembuf
           5.1.2.7 struct sem_undo
        5.1.3 Z}tHT|[g֐
           5.1.3.1 newary()
           5.1.3.2 freeary()
           5.1.3.3 semctl_down()
              5.1.3.3.1 IPC_RMID
              5.1.3.3.2 IPC_SET
           5.1.3.4 semctl_nolock()
              5.1.3.4.1 IPC_INFO  SEM_INFO
              5.1.3.4.2 SEM_STAT
           5.1.3.5 semctl_main()
              5.1.3.5.1 GETALL
              5.1.3.5.2 SETALL
              5.1.3.5.3 IPC_STAT
              5.1.3.5.4 GETVAL
              5.1.3.5.5 GETPID
              5.1.3.5.6 GETNCNT
              5.1.3.5.7 GETZCNT
              5.1.3.5.8 SETVAL
           5.1.3.6 count_semncnt()
           5.1.3.7 count_semzcnt()
           5.1.3.8 update_queue()
           5.1.3.9 try_atomic_semop()
           5.1.3.10 sem_revalidate()
           5.1.3.11 freeundos()
           5.1.3.12 alloc_undo()
           5.1.3.13 sem_exit()
     5.2 bZ[WL[
        5.2.1 bZ[WVXeR[C^[tF[X
           5.2.1.1 sys_msgget()
           5.2.1.2 sys_msgctl()
              5.2.1.2.1 IPC_INFO (܂ MSG_INFO)
              5.2.1.2.2 IPC_STAT (܂ MSG_STAT)
              5.2.1.2.3 IPC_SET
              5.2.1.2.4 IPC_RMID
           5.2.1.3 sys_msgsnd()
           5.2.1.4 sys_msgrcv()
        5.2.2 bZ[WƎ̍\
           5.2.2.1 struct msg_queue
           5.2.2.2 struct msg_msg
           5.2.2.3 struct msg_msgseg
           5.2.2.4 struct msg_sender
           5.2.2.5 struct msg_receiver
           5.2.2.6 struct msqid64_ds
           5.2.2.7 struct msqid_ds
           5.2.2.8 msg_setbuf
        5.2.3 bZ[WT|[g֐
           5.2.3.1 newque()
           5.2.3.2 freeque()
           5.2.3.3 ss_wakeup()
           5.2.3.4 ss_add()
           5.2.3.5 ss_del()
           5.2.3.6 expunge_all()
           5.2.3.7 load_msg()
           5.2.3.8 store_msg()
           5.2.3.9 free_msg()
           5.2.3.10 convert_mode()
           5.2.3.11 testmsg()
           5.2.3.12 pipelined_send()
           5.2.3.13 copy_msqid_to_user()
           5.2.3.14 copy_msqid_from_user()
     5.3 L
        5.3.1 LVXeR[C^[tF[X
           5.3.1.1 sys_shmget()
           5.3.1.2 sys_shmctl()
              5.3.1.2.1 IPC_INFO
              5.3.1.2.2 SHM_INFO
              5.3.1.2.3 SHM_STAT, IPC_STAT
              5.3.1.2.4 SHM_LOCK, SHM_UNLOCK
              5.3.1.2.5 IPC_RMID
              5.3.1.2.6 IPC_SET
           5.3.1.3 sys_shmat()
           5.3.1.4 sys_shmdt()
        5.3.2 LT|[g\
           5.3.2.1 struct shminfo64
           5.3.2.2 struct shm_info
           5.3.2.3 struct shmid_kernel
           5.3.2.4 struct shmid64_ds
           5.3.2.5 struct shmem_inode_info
        5.3.3 LT|[g֐
           5.3.3.1 newseg()
           5.3.3.2 shm_get_stat()
           5.3.3.3 shmem_lock()
           5.3.3.4 shm_destroy()
           5.3.3.5 shm_inc()
           5.3.3.6 shm_close()
           5.3.3.7 shmem_file_setup()
     5.4 Linux IPC v~eBu
        5.4.1 Z}tHAbZ[WыLŎgpėp Linux IPCv~eBu
           5.4.1.1 ipc_alloc()
           5.4.1.2 ipc_addid()
           5.4.1.3 ipc_rmid()
           5.4.1.4 ipc_buildid()
           5.4.1.5 ipc_checkid()
           5.4.1.6 grow_ary()
           5.4.1.7 ipc_findkey()
           5.4.1.8 ipcperms()
           5.4.1.9 ipc_lock()
           5.4.1.10 ipc_unlock()
           5.4.1.11 ipc_lockall()
           5.4.1.12 ipc_unlockall()
           5.4.1.13 ipc_get()
           5.4.1.14 ipc_parse_version()
        5.4.2 Z}tHAbZ[WыLŎgėp IPC \
           5.4.2.1 struct kern_ipc_perm
           5.4.2.2 struct ipc_ids
           5.4.2.3 struct ipc_id

  ______________________________________________________________________

  1.  u[g

  1.1.  LinuxJ[lC[W̍쐬

  ̏͂ł́ALinuxJ[lRpC鎞ɎXebvƊeX
  e[W̐ɂĉ܂BrhH̓A[LeN`ɂق
  ܂AłLinux/x86J[l̃rhɂĂl邱Ƃɂ
  ܂B

  [UA'make zImage'邢'make bzimage'ƃ^CvƁǍ
  ̋NC[ẂAꂼarch/i386/boot/zImage 
  arch/i386/boot/bzImage ɂȂ܂Bł́Aǂ̂悤ɃC[W
  邩Ă܂傤B

  1. C ƃAZũ\[Xt@ĆAELF Ĕzu\IuWFNg`
     (.o) ւƃRpCBɂ͘_IȃO[vƂ ar(1) 
     găA[JCu` (.a) ɂ̂B

  2. ld(1) gāAL .o  .a  'vmlinux' t@CւƃN
     B'vmlinux't@ĆAÓIɃNꂽXgbvO ELF
     32-bit LSB 80386 s`t@CłB

  3. System.map ́A'nm vmlinux' 쐬B֘AȂV{⍱
     ׂȃV{́Af}bvt@C珜OB

  4. arch/i386/boot fBNgɈڂB

  5. u[gZN^̃AZuR[h bootsect.S ́A^[Qbg bzImage
      zImage ɂ -D__BIG_KERNEL__  邩A邢͂Ȃ
     āAvvZbTBāAeX̏ꍇ
     bbootsect.s 邢 bootsect.s B
  6. bbootsect.s ̓AZuǍAbbootsect ƂO'rawo
     Ci'`ւƕϊB(邢́Abootsect.s AZu
     zImage  bootsect rawoCiϊ)

  7. ZbgAbvp̃R[h setup.S (setup.ŚAvideo.S܂)́A
     bzImagêƂbsetup.sցAzImage̎setup.sփvvZbT̏
     ʂo͂Bu[gZN^̃R[hƓ@ŏ
     AbzImagȅꍇɁA-D__BIG_KERNEL__^Ot^ƂɈႢ
     B́AbsetupƂO'rawoCi'`ւƕϊB

  8. arch/i386/boot/compressed ƂfBNgւƂA
     /usr/src/linux/vmlinux rawoCi`́A$tmppiggy (e|
     t@C)ւƕϊB܂̍ۂɁAELF tH[}bgł .note
     ZNV .comment ZNV폜B

  9. gzip -9 < $tmppiggy > $tmppiggy.gz

  10.
     $tmppiggy.gz  ELF Ĕzu\` (ld -r) piggy.o փNB

  11.
     head.S  misc.c Ȃ鈳k[`RpC(܂
     arch/i386/boot/compressed fBNg)B ELF IuWFNg`
      head.o ƁAmisc.o 𐶐B

  12.
     head.o  misc.oA piggy.o NAbvmlinuxƂ(邢
      zImagȅꍇ́Avmlinux ɂB /usr/src/linux/vmlinux ƊԈ
     Ȃ)BŁAvmlinux ł-Ttext 0x1000 Abvmlinux ̏ꍇ
     -Ttext 0x100000 ƂƂɈႢBbzImage ̈k[_
     high GAɃ[hB

  13.
     .note  .comment 2 ELF ZNV폜 bvmlinux  'raw
     oCi'` bvmlinux.outւƕϊB

  14.
     fBNg arch/i386/boot ֖߂Atools/build ɂvO
     gāA bbootsect + bsetup + kꂽ/bvmlinux.out  bzImage 
     ƂȂ킹(zImage ̏ꍇ́AeX b ̂Ȃ
     )B́A setup_sects Aroot_dev ̂悤ȏdvȕϐ
     Au[gZN^̍Ō̂ƂւƏށB

  u[gZN^̑傫́A512oCgłBsetup̃TCÝA4ZN^
  傫Ȃ΂Ȃ܂񂪁Aőł12KɐĂ܂B
  ̂悤ȃ[ŌvZ܂B

  0x4000 bytes >= 512 + setup ̃ZN^ * 512 + u[gZN^^setup
  sƂ̃X^bN̗̈

  ŁA̐ǂ炫Ă̂wԂƂɂ܂傤B

  bzImage ̃TCY̏́A_ł LILO ̃u[gŖ2.5M ƂȂ
  Ă܂BāAƂ΁Atbs[fBXNACD-ROM (El-Torito G
  ~[V[hɂ)ƂAraw C[W̃u[gł 0xFFFF
  pOt(0xFFFF0 = 1048560 oCg)ɂȂ܂B

   tools/build ́AJ[lC[W̃u[gZN^J[lC[
  WAsetup ̉TCY؂܂BAsetup ̏ɂẮA
  `FbN܂BāAsetup.S ̍Ōɗ]ȑ傫".space"t
  邾ŁAȒPɉꂽJ[l쐬łĂ܂܂B

  1.2.  u[g: T_

  u[gvZX̏ڍו̓A[LeN`ɈˑĂ܂B IBM
  PC/IA32 ̃A[LeN`֒ڂ邱Ƃɂ܂BÂfUCłA
  ߋւ̌݊ւ̖肩APC ̃t@[EGÁAIy[eBO
  VXeu[gƂɂ́AÂŋNĂ܂B̃vZX
  ́A 6 ̘_IȃXebvւƕł܂B

  1. BIOS ̓u[gfoCXIԁB

  2. BIOS ̓u[gfoCX̃u[gZN^[ւƓǂݍށB

  3. u[gZN^́Asetup Ɖ𓀃[`āAkꂽJ[l
     ݍށB

  4. J[ĺAveNg[hŉ𓀂B

  5. [x̏ asm R[hōsB

  6. nCx C ł̏sB

  1.3.  u[g: BIOS POST

  1. dANbNWFl[^JnB܂AoX
     #POWERGOOD MAT[gB

  2. CPU #RESET MAT[g (̎ CPU ́A8086 ݊̃A
     [hł)B

  3. %ds=%es=%fs=%gs=%ss=0, %cs=0xFFFF0000, %eip = 0x0000FFF0 (ROM BIOS
     POST R[h)B

  4. 荞݂֎~ꂽԂŁAׂĂ POST `FbNsB

  5. IVT (荞݃xNge[u) AhX 0 ֏B

  6. BIOS  u[gXgbv[_֐Aint 0x19 ɂĂяoB
     ̂ƂA%dl ́Au[gfoCX́uhCuԍvłB̊֐
     ́A gbN 0 ZN^ 1 Ԃ𕨗AhX 0x7C00 (0x07C0:0000) 
     ƓǂݍށB

  1.4.  u[g: u[gZN^ setup

  LinuxJ[lu[g邽߂Ɏgu[gZN^́A

  o  Linux u[gZN^ (arch/i386/boot/bootsect.S),

  o  LILO (邢͑̃u[g[_) u[gZN^A邢

  o  u[gZN^͂Ȃ(loadlinȂ)

     ̂ꂩɂȂ܂BŁALinuxu[gZN^̏ڍׂĂ݂܂B
     ŏ̐sł́AZOglɎg֋X̃}NĂ
     B

  ______________________________________________________________________
  29 SETUPSECS = 4                /* default nr of setup-sectors */
  30 BOOTSEG   = 0x07C0           /* original address of boot-sector */
  31 INITSEG   = DEF_INITSEG      /* we move boot here - out of the way */
  32 SETUPSEG  = DEF_SETUPSEG     /* setup starts here */
  33 SYSSEG    = DEF_SYSSEG       /* system loaded at 0x10000 (65536) */
  34 SYSSIZE   = DEF_SYSSIZE      /* system size: # of 16-byte clicks */
  ______________________________________________________________________

  (̐ bootsect.S t@C̍sԍł) DEF_INITSEG,
  DEF_SETUPSEG, DEF_SYSSEG  DEF_SYSSIZE ̒ĺA
  include/asm/boot.h Œ`ĂA

       ______________________________________________________________________
       /* Don't touch these, unless you really know what you're doing. */
       #define DEF_INITSEG     0x9000
       #define DEF_SYSSEG      0x1000
       #define DEF_SETUPSEG    0x9020
       #define DEF_SYSSIZE     0x7F00
       ______________________________________________________________________

  ƂȂĂ܂BāAۂbootsect.S̃R[hĂ܂傤B

       ______________________________________________________________________
           54          movw    $BOOTSEG, %ax
           55          movw    %ax, %ds
           56          movw    $INITSEG, %ax
           57          movw    %ax, %es
           58          movw    $256, %cx
           59          subw    %si, %si
           60          subw    %di, %di
           61          cld
           62          rep
           63          movsw
           64          ljmp    $INITSEG, $go

           65  # bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
           66  # wouldn't have to worry about this if we checked the top of memory.  Also
           67  # my BIOS can be configured to put the wini drive tables in high memory
           68  # instead of in the vector table.  The old stack might have clobbered the
           69  # drive table.

           70  go:     movw    $0x4000-12, %di         # 0x4000 is an arbitrary value >=
           71                                          # length of bootsect + length of
           72                                          # setup + room for stack;
           73                                          # 12 is disk parm size.
           74          movw    %ax, %ds                # ax and es already contain INITSEG
           75          movw    %ax, %ss
           76          movw    %di, %sp                # put stack at INITSEG:0x4000-12.
       ______________________________________________________________________

  54-63śAAhX 0x7C00  0x90000 փu[gZN^R[hړ
  ܂B́Â悤Ȏ菇ŎsĂ܂B

  1. %ds:%si  $BOOTSEG:0 (0x7C0:0 = 0x7C00) ݒ肷B

  2. %es:%di  $INITSEG:0 (0x9000:0 = 0x90000)ݒ肷B

  3. %cx 16rbg̃[hl (256 [h = 512 oCg = 1 Z
     N^)B

  4. IɃAhXZ悤(cld)ɁAEFLAGS  DF (direction) t
     ONAB

  5. ɐi݁A 512 bytes (rep movsw)Rs[B

  ̃R[hrep movsdgȂ̂́AʂȗR܂B(qg
  .code16) 64sڂł́AVꂽu[gZN^̃Rs[̃xgo:
  WvB܂AZOg 0x9000łBƑ3̖(64-76
  s)ł́A$INITSEG:0x4000-0xCփX^bNݒ肵Ă܂B܂A%ss =
  $INITSEG (0x9000)  %sp = 0x3FF4 (0x4000-0xC) łBɑOosetup
  ̃TCYǂ炫Ă邩̗R܂ (Linux J[lC[
  W̍쐬 Q)B

  77-103sł́A߂̃fBXNp[^e[u㏑āA}`Z
  N^ǂݍ݂ł悤ɂ܂B

       ______________________________________________________________________
           77  # Many BIOS's default disk parameter tables will not recognise
           78  # multi-sector reads beyond the maximum sector number specified
           79  # in the default diskette parameter tables - this may mean 7
           80  # sectors in some cases.
           81  #
           82  # Since single sector reads are slow and out of the question,
           83  # we must take care of this by creating new parameter tables
           84  # (for the first disk) in RAM.  We will set the maximum sector
           85  # count to 36 - the most we will encounter on an ED 2.88.
           86  #
           87  # High doesn't hurt.  Low does.
           88  #
           89  # Segments are as follows: ds = es = ss = cs - INITSEG, fs = 0,
           90  # and gs is unused.

           91          movw    %cx, %fs                # set fs to 0
           92          movw    $0x78, %bx              # fs:bx is parameter table address
           93          pushw   %ds
           94          ldsw    %fs:(%bx), %si          # ds:si is source
           95          movb    $6, %cl                 # copy 12 bytes
           96          pushw   %di                     # di = 0x4000-12.
           97          rep                             # don't need cld -> done on line 66
           98          movsw
           99          popw    %di
          100          popw    %ds
          101          movb    $36, 0x4(%di)           # patch sector count
          102          movw    %di, %fs:(%bx)
          103          movw    %es, %fs:2(%bx)
       ______________________________________________________________________

  BIOS ̃T[rX int 0x13 t@NV0 (reset FDC) gāAt
  bs[fBXNRg[Zbg܂BāAsetup ZN^
  bootsector ̂֓ǂݍ܂܂B܂ AhX0x90200
  ($INITSEG:0x200) łBāAēxBIOST[rXint 0x13 t@NV
   2(read sector(s)) Ăяo܂B̕ӂ́A107-124sɋLq
  ܂B

       ______________________________________________________________________
          107  load_setup:
          108          xorb    %ah, %ah                # reset FDC
          109          xorb    %dl, %dl
          110          int     $0x13
          111          xorw    %dx, %dx                # drive 0, head 0
          112          movb    $0x02, %cl              # sector 2, track 0
          113          movw    $0x0200, %bx            # address = 512, in INITSEG
          114          movb    $0x02, %ah              # service 2, "read sector(s)"
          115          movb    setup_sects, %al        # (assume all on head 0, track 0)
          116          int     $0x13                   # read it
          117          jnc     ok_load_setup           # ok - continue

          118          pushw   %ax                     # dump error code
          119          call    print_nl
          120          movw    %sp, %bp
          121          call    print_hex
          122          popw    %ax
          123          jmp     load_setup

          124  ok_load_setup:
       ______________________________________________________________________

  AȂɂ̌(tbs[򉻂ĂƂAgpɃfBXPbg
  𔲂Ƃ)œǂݍ݂sAG[R[h\ȂA
  ɍĎs܂BĎsĂȂԂ甲oɂ́Ap\
  RċNق܂BAʏ킱̂悤ȂƂ͋N܂
  (ȂɂԈႦĂƂAPɂȂ̂ł)B
  Asetup̃R[hsetup_sectZN^̓ǂݍ݂܂sƁAx
  ok_load_setup: փWv܂B̌AkꂽJ[lC[W
  AhX 0x10000 ւƓǂݍ݂܂B́Aʂ̃̈
  (0-64K) ɂt@[EGÃf[^̈ی삷邽߂ɍsĂ
  BJ[lǂݍ܂ƁA$SETUPSEG:0 (arch/i386/boot/setup.S)
  Wv܂Bt@[̃f[^vȂȂ (Ⴆ΁ABIOS
  R[ȂȂ)AikꂽjׂẴJ[l̃C[W
  0x10000  0x1000 (RAAhX)ֈڂ܂B̌ʁÄ̗
  ͏㏑܂B́Asetup.SŎs܂B̃R[hł́Av
  eNg[hւ̈ڍsɕKvȂƂsAkJ[l̐擪ł
  0x1000 ւƃWv悤ɂȂĂ܂B܂Aarch/i386/boot/com-
  pressed/{head.S,misc.c} łBɁAX^bNݒ肵Adecom-
  press_kernel() Ăяo܂B̃[`ł̓J[lAhX
  0x100000 ֓WJ܂BāA̓WJꂽJ[lփWv
  B

  ŌÂu[g[_(ÂLILO)ł́Asetup̍ŏ4ZN^ǂݍ
  Ƃł܂B̂߁AKvłΎg̎cǂݍނ
  setup̃R[h݂Ă܂BAsetup ̃R[h͗lXȃ^
  Cv/o[W̃[_zImage/bzImagȇg킹舵Ȃ΂
  ܂B̂߁AɕGłB

  ŁA"bzImage" ƂĒmĂ傫ȃJ[l̃[hsu[g
  ZN^R[hł̑Ώ@Ă݂܂傤B setup̃ZN^́A
  0x90200Ƀ[h܂A̎̃J[ĺAx64Ǩł܂œ
  ݍ܂悤ȓʂȕ⏕[`g܂B̃[`́Af[^
  ʃAhXAʃAhXֈړBIOSR[Ăяo܂B
  ⏕[`́Asetup.Sbootsect_kludgexQƂ܂B
  bootsect_helperƂsetup.SŒ`Ă܂B setup.S
  bootsect_klughx́AsetupZOglƁA̒bootsect_helper
  R[h̃ItZbgȂĂ܂B̂߁Au[gZN^ł́AW
  v̂lcall߂gƂł܂B(܂ZOgWv
  ) setup.Sɂꂪ̂́APbootsect.Sɂ́A]ȃXy[X
  Ȃ̂łBi͌ɂ͐͂܂ -- bootsect.S
  ́A4oCgƏȂƂ1oCg̗]T܂BA炩ɏ\
  Ƃ͂܂)B̃[`͍ʂ̃ֈړ̂ɁAint
  0x15(ax=0x8700)BIOST[rXgA%es0x10000悤Zb
  g܂B́Abootsect.S̃R[hŁAfBXNf[^Rs[
  ƂɒʃȂȂȂƂۏ؂܂B

  1.5.  LILOu[g[_ƂĎg

  Linuxu[gZN^𗇂Ŏg킸Aʂȃu[g[_(LILO)gƂŁA
  _܂܂B

  1.  Linux J[lIAɂ͕ OS Ił
     悤ɂȂ܂B

  2. J[lɃR}hCp^nƂł悤ɂȂ܂ (
      bootsector+setup ɂ̋@\tł BCP Ƃpb`
     ܂)B

  3. TCY̑傫 bzImage J[l[h邱Ƃł܂B1M
     ܂ł̂Ƃ낪 2.5M ܂ŉ\ɂȂ܂B

  LILO ̌Âo[W(v17ȑO)ł́AbzImage J[l[h邱Ƃ
  ł܂BVo[Wł(NOŋ߂
  )Abootsect+setup Ɠ悤ɁABIOS T[rXɂʃ獂
  ʃփf[^ړeNjbNgĂ܂BlɂĂ(
  Peter Anvin)AzImage T|[g͍폜ׂƎ咣Ă܂B
  cĂȗŔA(Alan Cox ɂ) zImage ̃[h͉\
  AbzImage J[l̃u[głȂ悤ȉꂽ BIOS 炩ɑ
  Ă邽߂ƂƂłB

  LILO ͍ŌɁAsetup.SփWvAʏǂ̏𑱂܂B

  1.6.  x̏

  ux̏vł́Au[gɒڊ֘AȂ̂ɂčl
  BAsR[ḧꕔ́AWJꂽJ[l̐擪ɂ
  arch/i386/kernel/head.SƌĂ΂AZuŏĂ܂B
  ́Aȉ̂悤ȏs܂B

  1. ZOgl (%ds = %es = %fs = %gs = __KERNEL_DS =
     0x18)B

  2. y[We[uB

  3. %cr0PGrbgZbgAy[WOLɂB

  4. BSS[Ŗ߂ (SMPł́AP߂CPȔs)B

  5. u[gp[^̍ŏ2kRs[ (J[lR}hC)B

  6. CPU^CvEFLAGSƁA\ł386ȏmFłcpuidŃ`FbN
     B

  7. P߂CPUstart_kernel()ĂяoACPÚAready=1łΒP
      esp/eip [ĥ݂Ŗ߂ĂȂ֐
     arch/i386/kernel/smpboot.c:initialize_secondary() ĂяoB

  init/main.c:start_kernel()CŏĂAȉ̂悤ȏs
  B

  1. (̊Ԃɂ͂PCPU삷邱ƂKvȂ)O[o
     J[lbN擾B

  2. A[LeN`Ǝ̃ZbgAbvs(CAEg̉́A
     u[gR}hC̍ēx̃Rs[Ȃ)B

  3. Linux J[l̃o[WArhɎgpRpCȂǂȂ
     uoi[vbZ[Wp̃J[lOobt@֏ށB
     bZ[ẂAinit/version.c Œ`Ă linux_bannar ϐ
     擾B̃bZ[ẂAcat /proc/version R}hs
     ƓbZ[WɂȂĂB

  4. trap B

  5. irq B

  6. XPW[̎gf[^B

  7. ێf[^B

  8. \tg荞݃TuVXeB

  9. u[gR}hCIvV͂B

  10.
     R\[B

  11.
     W[T|[gJ[lɑgݍ܂ĂAIW[
     ǂݍ݋@\B

  12.
     A"profile=" R}hC΁Avt@Cobt@
     B

  13.
     kmem_cache_init() sAقƂǂ̃XuAP[^
     B

  14.
     荞݂LɂB

  15.
     gpĂ CPU  BogoMips vZB

  16.
     max_mapnrAtotalram_pages  high_memoryvZmem_init()Ă
     oA"Memory: ..." ̍s\B

  17.
     kmem_cache_sizes_init() sAXuAP[^̏
     B

  18.
     procfs gf[^\̂B

  19.
     fork_init()ĂяoAuid_cache 쐬āAp\ȃʂɊ
     Âmax_threadsA  init_task  max_threads/2 ɂȂ悤
     RLIMIT_NPROC ݒ肷B

  20.
     VFSAVMAobt@LbVȂǂŕKvȎX̃XuLbV쐬
     B

  21.
     System V IPC T|[gJ[lɊ܂܂ĂAIPC TuVXe
     BSystem V shm ̏ꍇ́Ashmfst@CVXe(J[l
     )CX^X}Eg邱Ƃɒӂ邱ƁB
  22.
     quota T|[gJ[lɊ܂܂ĂAquota p̃XuLb
     V쐬B

  23.
     A[LeN`ĹuoÕ`FbNvsBČ_ŉ\
     AvZbToXȂ̑ΏLɂBẽA[LeN
     `rƁAuIA64 ɂ̓oO͂ȂvAuIA32 ͂ȂoO
     vB̗ǂƂāuf00foOvB̃oÓAJ[l
     686 O CPU ɃRpCꂽƂ`FbNA`Fb
     Nʂɏ]ΏsȂB

  24.
     XPW[ű@vɋN鎖tOZbgB
     āAinit J[lXbh쐬B̃J[lXbh́A
     A"init=" u[gp[^^Ăꍇ́A
     execute_command sBw肪Ȃ
     ΁A/sbin/initA/etc/initA/bin/initA/bin/sh̏Ƀt@CTA
     s悤ƂBSĎsA"init="p[^g悤
     uvăpjbNԂɂȂB

  25.
     ACh[vɓB pid=0 ̃AChXbhƂȂB

  ŏdvȂƂ́Ainit() J[lXbh do_basic_setup() Ă
  oĂ邱ƂłB̊֐͂ɁA__initcall  module_init() }N
  ɂēo^ꂽ֐̃XgǂݏoĎs do_initcalls() 
  Ăяo܂B̊֐́AeX݂ɈˑĂȂAMakefile
  N̏ւ邱ƂŁAˑ֌W蓮ŏCĂ܂B
  ͂Ȃ킿Ac[̒̃fBNg̈ʒuMakefile̍\ɂāA
  ֐̎sւƂƂӖĂ܂BƂ
  ́A̃TufBNgABꍇABA̒̏֐Ɉˑ
  Ă悤ȏꍇɁȀdvɂȂ܂BAAÓIɃJ[l
  ɃNAB̓W[łꍇ́AB̎s^C~ÓAA
  KvȊ𐮂ł邱Ƃۏ؂܂BAAW[ł
  ABRW[łꍇɂ͂܂BAAB
  ÓIɃJ[lɃNꍇ͂ǂł傤? 2̎śA
  J[lC[W.initcall.init ELF ZNVɂʒu̍Ɉˑ
  Ă̂łB Rogier Wolff͊KwIȁuDxv\ĂA
  ăJǂ(ݓI)ŃW[N邩悤
  ɂ܂BA܂̂ƂAJ[l֎󂯓悤
  ʓIɃGKgȕ@Ŏpb`݂͑Ă܂B
  āAN̏𐳂ȂƂȂ̂łBAL̗ŁAAB
  ƂɐÓIɃRpCꂽƂǍDɓ삵ȂAɓ삵܂
  Â߂ɂ͂ȂMakefileɏ悭XgȂ΂Ȃ܂B
  ܂Ȃ悤ȂAIuWFNgt@C̃Xgς邱Ƃ
  Ȃ܂Bӂ鉿l̂̎ƂāA"init="u[gR}
  hCnƂɂAuʂinitvOvsLinux̋@\
  ܂B́A/sbin/init ď㏑Ƃ̉񕜂A
  (rc)XNvg /etc/initttab AɈŎs邱Ƃ
  fobÔɗLvłB

  1.7.  x86łSMPu[g

  SMPɂāABP  start_kernel()֐i݁Asmp_init()Ɠ
  src/i386/kernel/smpboot.c:smp_boot_cpus()ɐiނ܂ŁAʏ̃u[gZ
  N^AsetupȂǂ̃u[gV[PXił܂B smp_boot_cpus()
  ́A(NR_CPUS܂)[vŊeapicidƂɎsA̒do_boot_cpu()
  Ă΂܂B do_boot_cpu()̓^[QbgCPUp̃ACh^XN
  (i.e. fork_by_hand)܂BāAIntel MPdlŒ`Ă
  ̈ʒu (0x467/0x469) ւƁAtrampoline.Sɂg|R[hEIP
  ݂܂BāAAP trampoline.S̃R[hs悤ɁA
  ^[Qbg CPU  STARTUP IPI 𐶐܂B

  u[g CPU ́Aʃɂe CPU ̃g|R[h̃Rs[
  쐬܂BAPR[h̓}WbNio[g̃R[hɖߍނ
  ŁABPɂ肻APg|R[hsĂ悢̔fs킹
  BIntel MPdlɂċK肳Ă邽߁Ag|R[h͒ʃ
  ɒuKv܂B

  g|R[h͒P %bx WX^ 1 ɂ܂BāAveN
  g[hɈڂAarch/i386/kernel/head.S̃CGg[|Cgł
  startup_32 ւƃWv܂B

  āAAPhead.S̎sJnAgBPł͂ȂƂɋCt܂B
  ƁABSSNAR[h̎sXLbvāAinitalize_secondary()
  ւƐi݂܂BāA CPU ̓ACh^XNւƒPɐi݂܂B --
  init_tasks[cpu]́ABPdo_boot_cpu(cpu) sƂɂłɏ
  ĂƂvN܂傤B

  ŁAinit_task͋Lł܂AeAChXbhŊeX TSS 
  Ȃ΂ȂȂƂɒӂ܂傤B́Ainit_tss[NR_CPUS]z
  ɂȂĂ闝RɂȂĂ܂B

  1.8.  f[^уR[h̉

  Iy[eBOVXegƂÂ߂̂قƂǂ
  R[hƃf[^\͓̂xƎg邱Ƃ͂܂BقƂǂ̃Iy
  [eBOVXe(BSD, FreeBSD etc...)ł́A̕sKvȏj
  邱Ƃł܂BȂ킿AMdȕJ[lQĂ
  ƂɂȂ̂łBނ̎g(McKusick4.4BSD{Q)́Au֘A
  ̃R[hẽTuVXeɍLĂÂ͌I
  ł͂ȂBvƂƂłBLinux ͂Â悤Ȍ܂
  BȂȂALinux ł́AuȂɂIɉ\ł΁A͂
  łɎĂ邩ANƂĂvłB

  āAȌ͂ŏqׂ悤ɁALinux J[lELF oCiƂĂ̂݃R
  pCł邱ƂAɂꂪ\ȂƂ(邢́A̍
  ̈)Ă܂Bȉ̂悤Ɏg2̃}N Linux 
  񋟂ĂAR[h/f[^p邱Ƃł悤ɂȂĂ
  ܂B

  o  __init - R[hp

  o  __initdata - f[^p

  include/linux/init.hɒ`gcc̑wq("gcc magic"
  Ăm)]܂B

       ______________________________________________________________________
       #ifndef MODULE
       #define __init        __attribute__ ((__section__ (".text.init")))
       #define __initdata    __attribute__ ((__section__ (".data.init")))
       #else
       #define __init
       #define __initdata
       #endif
       ______________________________________________________________________

  ꂪӖ邱Ƃ́AR[hJ[lɐÓIɃRpCĂ
  Ȃ(܂ MODULE`ĂȂ΁jA ELF ZNV
  text.initɂ̃R[hzuƂƂłBĂ̔zu
  ́Aarch/i386/vmlinux.lds̃J}bvɒ`̂łBt(܂
  W[ł)}N͂ȂɂȂƂƂłB

  u[gɁAAhX__init_begin__init_end̊Ԃ̑SẴy[W
  AA[LeN`L̊֐free_initmem()A"init"J[lXb
  h(֐init/main.c:init())ĂяôłB

  (̃[NXe[V̂悤)ʓIȃVXeł́ǍʁA260K
  ̃̉ɂȂ܂B

  module_init()ɂēo^ꂽ֐́A.initcall.initɔzuAÓI
  ɃNĂƂɂ͓lɉ܂BLinux J݂̌̕
  ł́ÃTuVXeKvɉăW[ł悤ɁA(
  W[̕Kv̂Ȃ)TuVXȅꍇɂAfUC̏i
  KAinit/exit Gg[|Cg񋟂悤ɂĂ
  Bfs/pipe.cpipefsÂ悢łBƂAbdflush (fs/buffer.c
  Q)̂悤ɁATuVXeăW[ɂȂ邱ƂȂA
  ̎_ł̊֐ĂԂƂdvłȂƂĂAł֐Ƃ
  module_init()}NgƂ͂悢ƂłB

  ɓ悤Ȏg__exit__exitdataƂO2̃}N
  ܂B́AW[T|[gɂ蒼ړIɂȂ邽
  ߁ÃZNVɂĐ܂B

  1.9.  J[lR}hC

  ŁAu[gɃJ[lɓnꂽR}hCɉN邩l
  Ă݂܂傤B

  1. LILO(ȂBCP)  BIOS ̃L[{[hT[rXgāAR}h
     C󂯎BāÅ̈ʒuɁAɗLȃR}
     hC邱ƂƂɊi[B

  2. arch/i386/kernel/head.S ͎g̍ŏ 2k [y[W̊OւƃR
     s[B

  3. (start_kernel() Ă΂ꂽ setup_arch()Ăяo)
     arch/i386/kernel/setup.c:parse_mem_cmdline()́A[y[W 256
     oCg /proc/cmdline ŕ\̂Ɠ  saved_command_line 
     ƃRs[BƓ[`́A"mem=" IvVΏ
     AVM p[^K؂ɒB

  4. b(start_kernel()Ă΂) parse_options() ̃R}hC
     ߂ƁÅ֐́uJ[lvp[^(_ł́A"init="
     init ̊ϐA)Ae[hchecksetup()ւƓnB

  5. checksetup()  ELF ZNV.setup.init̃R[hɂāÅe
     ֐NAR}hC}b`ẮAR}hC
     [hnĂBŁA__setup()œo^ꂽ֐̕Ԃl
     0 ̂Ƃ́A"variable=value" ȏ̊֐֓nA
     "value"̊֐ł͖ŁAł͗LłƂƂ\
     ĂB Jeff GarziḱAuƂnbJ[͂yy
      :) vƃRgĂBȂ?  ͖炩 ID ̏ɓ
     LŁA܂肠鏇ŃNꂽJ[l͊֐A֐B̑OɋN
     邪AłȂꍇ́At̏ɂȂ茋ʂɈˑĂ܂
     炾B

  āAu[gR}hCR[h͂ǂ̂悤ɂȂĂ̂
  傤Binclude/linux/init.hŒ` __setup() }Ng
  B

  ______________________________________________________________________

  /*
   * Used for kernel command line parameter setup
   */
  struct kernel_param {
          const char *str;
          int (*setup_func)(char *);
  };

  extern struct kernel_param __setup_start, __setup_end;

  #ifndef MODULE
  #define __setup(str, fn) \
     static char __setup_str_##fn[] __initdata = str; \
     static struct kernel_param __setup_##fn __initsetup = \
     { __setup_str_##fn, fn }

  #else
  #define __setup(str,func) /* nothing */
  endif
  ______________________________________________________________________

  ɁAۂ̃R[hł̓T^IȎg͈ȉ̂悤ɂȂ܂ (ۂ̃h
  Co BusLogic HBA drivers/scsi/BusLogic.cp)B

       ______________________________________________________________________
       static int __init
       BusLogic_Setup(char *str)
       {
               int ints[3];

               (void)get_options(str, ARRAY_SIZE(ints), ints);

               if (ints[0] != 0) {
                       BusLogic_Error("BusLogic: Obsolete Command Line Entry "
                                       "Format Ignored\n", NULL);
                       return 0;
               }
               if (str == NULL || *str == '\0')
                       return 0;
               return BusLogic_ParseDriverOptions(str);
       }

       __setup("BusLogic=", BusLogic_Setup);
       ______________________________________________________________________

   __setup()̓W[ɑ΂Ă͉܂BăW[
  ÓIɃNĂ̂łAu[gR}hC
  R[hł́AW[̏[`ɂāAg̉͊֐
  ĂNȂ΂ȂȂłB́AÓIɃRpC
  鎞ȂǂłȂAW[ƂăRpC鎞ɂAp[^
  R[hƂłƂł܂B

  2.  vZXƊ荞݊Ǘ

  2.1.  ^XN\̂ƃvZXe[u

  Linuxł́ASẴvZX struct tack_struct \̂IɊ蓖
  ܂BLinux œő̃vZX̐́A݂镨
  eʂŌ܂܂ (kernel/fork.c:fork_init()Q)B̒l͈ȉ̂Ƃ
  łB܂A

       ______________________________________________________________________
               /*
                * The default maximum number of threads is set to a safe
                * value: the thread structures can take up at most half
                * of memory.
                */
               max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 2;
       ______________________________________________________________________

  ɂȂ܂B

  IA32 A[LeN`ł́A{I num_physpages/4 ӖĂ܂B
  ΁A512M ̃}V΁A32k ̃Xbh𐶐łƂ
  B͌Â (2.2 ₻ȑO) J[l 4k ̐ɔבȉ
  PɂȂĂ܂B̂AsɃJ[l𒲐ł
  KERN_MAX_THREADS sysctl(2) AP procfs C^[tF[Xg
  ύX邱Ƃł܂B

       ______________________________________________________________________
       # cat /proc/sys/kernel/threads-max
       32764
       # echo 100000 > /proc/sys/kernel/threads-max
       # cat /proc/sys/kernel/threads-max
       100000
       # gdb -q vmlinux /proc/kcore
       Core was generated by `BOOT_IMAGE=240ac18 ro root=306 video=matrox:vesa:0x118'.
       #0  0x0 in ?? ()
       (gdb) p max_threads
       $1 = 100000
       ______________________________________________________________________

  Linux VXeł́AvZXQ͂Qނ̈قȂ@ŃNꂽ
  struct task_struct \̂̏WƂĕ\Ƃł܂B

  1. pid ɂnbVꂽnbVe[uƁA

  2. p->next_task  p->prev_task |C^p~̃_uN
     XgB

  nbVe[úApidhash[] ƌĂ΂Ainclude/linux/sched.h Œ`
  Ă܂B

       ______________________________________________________________________
       /* PID hashing. (shouldnt this be dynamic?) */
       #define PIDHASH_SZ (4096 >> 2)
       extern struct task_struct *pidhash[PIDHASH_SZ];

       #define pid_hashfn(x)   ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
       ______________________________________________________________________

  ^XNpidl̃nbVɂAL̃nbV֐͂(0PID_MAX-1
  )̈ɗvfψɕU悤ɂȂĂ܂BnbVe[u
  ́Ainclude/linux/sched.h ̒ɂ find_task_pid() gāA^
  ꂽ pid ̃^XNɌ悤gĂ܂B

       ______________________________________________________________________
       static inline struct task_struct *find_task_by_pid(int pid)
       {
               struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];

               for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
                       ;

               return p;
       }
       ______________________________________________________________________

  enbVXg(܂蓯lɃnbVꂽ)^XN
  ́Ap->pidhash_next/pidhash_pprevɂăNAhash_pid()
  unhash_pid()nbVe[uɂvZX}폜肷
  ̂Ɏg܂B̑́AWRITÊ߂Ɏ擾tasklist_lock
  ǂݏXsbN̕ی̂ƍs܂B

  p->next_task/prev_taskgȎoNXǵAVXe
  ׂẴ^XNɗeՂɓBł悤ɊǗ܂B
  ́Ainclude/linux/sched.hŒ`for_each_task()}NɂĎ
  Ă܂B

       ______________________________________________________________________
       #define for_each_task(p) \
               for (p = &init_task ; (p = p->next_task) != &init_task ; )
       ______________________________________________________________________

  for_each_task()̃[UREAD  tasklist_lock 擾Kv
  BŁAfor_each_task()Xg̎n_(ƏI_)\̂init_task
  gpĂ܂B́AACh^XN(pid 0)I邱ƂȂ
  ASȕ@łB

  vZXnbVe[u܂̓vZXe[uN̕ύXɂ́A
  fork()exitAptrace() łAWRITÊ߂tasklist_lock擾Ȃ
  ΂Ȃ܂BƋ[Ƃɂ́A݂śA[J
  CPŮ荞݂ɂȂ΂ȂȂ̂łBɂ͖ȗR
  ܂Bsend_sigio()֐̓^XNXgǂāAREAD̂
  tasklist_lock擾A荞݃ReLXg kill_fasync()Ă
  o邩łBꂪAǂݍ݂sƂɂ͕svłA݂s
  Ƃɂ͕K荞݂𖳌ɂȂ΂ȂȂRłB

  āAtask_struct\̂ǂ̂悤ɂđ݂ɃNĂ邩Ă
  ܂傤B task_struct̃o[qׂɂ݂Ă݂܂B݂͑Ɍ
  Ă UNIX 'struct proc' 'struct user' Ǝア֘A܂B

  UNIX ̑̃o[Wł́A^XNԂ̏2ɕĊi[܂B
  ͏Ƀɖ΂ȂȂ('proc structure'Ƃ΂AvZ
  XԁAXPW[OȂǂ܂ł)̂łB́Av
  ZXsƂɂKvɂȂ('u area'ƌĂ΂At@CfBX
  Nv^e[uAfBXNNI^Ȃǂ)łB̂悤ȏX
  Ȃꂽ̂́APɃɋMdȎłƂ
  ܂BOSł́A(񍡊wł Linux łȂA̗Ⴆ
   FreeBSD ł́ALinux̂̕ɐîɂȂĂ)
  ̂悤ɕKv͂ȂA䂦Ƀɂf[^\̂
  vZXԂ̊Ǘs悤ɂȂĂ܂B

  task_struct\̂́A include/linux/sched.hŐ錾ÃTCY͌
   1680 byte łB

  ԃtB[ĥ͎悤ɐ錾Ă܂B

       ______________________________________________________________________
       volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */

       #define TASK_RUNNING            0
       #define TASK_INTERRUPTIBLE      1
       #define TASK_UNINTERRUPTIBLE    2
       #define TASK_ZOMBIE             4
       #define TASK_STOPPED            8
       #define TASK_EXCLUSIVE          32
       ______________________________________________________________________

  Ȃ TASK_EXCLUSIVE  16ł͂Ȃ32ƒ`Ă̂ł傤B
  16 TASK_SWAPPING ɂgĂA(2.3.x̂ǂ
  )TASK_SWAPPING̃t@X폜Ƃ TASK_EXCLUSIVEVtg
  ̂YĂ܂Ȃ̂łB p->statevolatileCq́A(
  ݃nh)񓯊ŕύX꓾邱ƂӖĂ܂B

  1. TASK_RUNNING:^XN runL[ɂuł낤vƂӖ
     BrunL[ɂȂȂ^XNTASK_RUNNINGĂ
     ŔArunqueueɒu삪Ag~bNłȂłB runL[
     ׂɂ͓ǂݍ݂̂߂ runqueue_lock ǂݏXsbN擾
     KvBƁǍ runqueue ̊e^XN
     TASK_RUNNING Ԃɂ邩ǂ邾낤BAL̗R
     ́At͐^ɂȂȂBl, hCog(sĂvZX
     ̃ReLXgɊւ炸)TASK_INTERRUPTIBLE (
     TASK_UNINTERRUPTIBLE) Ƀ}[NłB Ă̌A schedule() 
     ĂяoB (runqueue ɎcP[XłۗꂽVOi
     Ȃ) runqueue炻폜B

  2. TASK_INTERRUPTIBLE: ^XN͋x~Ă邪AVOi^C}̏I
     ŋN邱ƂB

  3. TASK_UNINTERRUPTIBLE: TASK_INTERRUPTIBLEƓANȂ_
     قȂĂB

  4. TASK_ZONBIE: ^XN͏IĂ邪ȀԂ(ʏ킩A_vV
     ɂ)evZXɂ(wait()ɂ)ĂȂB

  5. TASK_STOPPED: WuVOiptrace(2)ɂA^XN~
     B

  6. TASK_EXCLUSIVE: ͓ƗԂł͂ȂATASK_INTERRUPTIBLE 
     TASK_UNINTERRUPTIBLE  OR B̑̃^XNƂɃEG
     CgL[ŋx~ĂƂASĂ̑ҋ@^XNN
     "thundering herd"NɁAN邱ƂӖ
     B

  ^XNtO͑ݔrIł͂ȂvZXԂɂĂ̏񂩂ȂĂ
  ܂B

       ______________________________________________________________________
       unsigned long flags;    /* per process flags, defined below */
       /*
        * Per process flags
        */
       #define PF_ALIGNWARN    0x00000001      /* Print alignment warning msgs */
                                               /* Not implemented yet, only for 486*/
       #define PF_STARTING     0x00000002      /* being created */
       #define PF_EXITING      0x00000004      /* getting shut down */
       #define PF_FORKNOEXEC   0x00000040      /* forked but didn't exec */
       #define PF_SUPERPRIV    0x00000100      /* used super-user privileges */
       #define PF_DUMPCORE     0x00000200      /* dumped core */
       #define PF_SIGNALED     0x00000400      /* killed by a signal */
       #define PF_MEMALLOC     0x00000800      /* Allocating memory */
       #define PF_VFORK        0x00001000      /* Wake up parent in mm_release */
       #define PF_USEDFPU      0x00100000      /* task used FPU this quantum (SMP) */
       ______________________________________________________________________

  p->has_cpu p->processor, p->counter, p->priority, p->policy 
  p->rt_prioritytB[h̓XPW[Ɗ֘A邽߁AقǌĂ
  ܂B

  p->mm  p->active_mm tB[h͂ꂼAvZX mm_struct \
  ̂ŕ\AhXԂƁAvZXAȃAhXԂ
  (e.g. J[lXbh)́AANeBuȃAhXԂĂ
  B̓^XNXPW[ɂ蒆~Ƃ̃AhXԃXCb`
  ɂTLBtbVŏɂĂ܂BāA(p->mm
  Ȃ)J[lXbhXPW[CƂ́Anext->active_mm
  ̓XPW[AEgꂽ^XNprev->active_mmɐݒ肳܂B
  ^XŃAprev->mm != NULL łƂprev->mmɓȂ
  B CLONE_VMtOclone(2)VXeR[ɓnꂽƂAvfork(2)
  VXeR[ɂƂ́AAhXԂ̓XbhŋL܂B

  p->exec_domain  p->personality tB[h̓^XÑp[\ieB
  ֘AĂ܂B܂AVXeR[UNIX"personality"
  G~[g邽߂ɐU镑@ɂȂĂ܂B

  p->fstB[h̓t@CVXe񂩂ȂALinuxɂẮAO
  vfӖ܂B

  1. [gfBNgdentryƃ}Eg|Cg

  2. փ[gfBNgdentryƃ}Eg|Cg

  3. ݂̃[LOfBNgdentryƃ}Eg|Cg

  ̍\̂̓t@XJEgێ܂B́ACLONE_FStO
  clone(2)VXeR[ɓnꂽƂɁAN[̃^XNԂŋLł
  悤ɂ邽߂łB

  p->filestB[h́At@CfBXNv^e[uȂĂ܂B
  CLONE_FILESclone(2)VXeR[Ŏw肳ꂽƂɃ^XNԂ
  L܂B

  p->sigtB[h́AVOinhȂĂ܂B
  CLONE_SIGHANDɂN[̃^XNԂŋL܂B

  2.2.  ^XNƃJ[lXbh̐ƏI[

  Iy[eBOVXȇ̏Ђł́AuvZXvꂼႤ悤
  ɒ`Ă܂Bus̃vÕCX^XvɎn܂A
  uclone(2)fork(2)VXeR[ɂ萶́v܂ŗlX
  BLinuxɂẮAO̃vZX̎ނ܂B

  o  AChXbh

  o  J[lXbh

  o  [U^XN

  AChXbh̓RpCɈ߂CPÛ߂ɍ܂B
  u蓮vŃA[LeN`Larch/i386/kernel/smpboot.c
  fork_by_hand()ɂeCPUƂɍ܂B̊֐ł́Afork(2)VX
  eR[(A[LeN`ɂĂ)œWJĂ܂BACh^
  XN͈init_task\̂L܂ATSS\̂͌ʂCPUƂ
  zinit_tssƂĎĂ܂BACh^XNׂ͂ pid=0 ƂȂ
  Ã^XN pidLł܂B͂܂ CLONE_PIDtO
  clone(2)ւƓnƂƂłB

  J[lXbh́AJ[l[h clone(2) VXeR[Ăяo
  kernel_thread()֐gĐ܂BJ[lXbh͒ʏ탆[U
  AhXԂ܂(܂p->mm = NULL)B́ÃXbh
  A(Ƃdaemonize()֐ʂ)exit_mm()słB
  J[lXbh́AłJ[lAhXԂ֒ڃANZXł
  BāAȒlpidԍ蓖Ă܂B(x86̂Ƃ) vZb
  TO0 ősĂƂ́AJ[lXbhׂĂI/Ǒ
  AXPW[ɑ΂ăvGveBuł͂ȂƂƂӖ
  ܂B

  [U^XŃAclone(2)Ȃ́Afork(2)VXeR[ɂ
  B̃VXeR[́AIkernel/fork.c:do_fork()Ăяo
  Ă܂B

  ŁA[UvZXfork(2)VXeR[ĂяoƂɁA
  NĂ邩܂傤Bfork(2)[UX^bN⃌WX^n
  @قȂƂӖŃA[LeN`ˑƂĂAɂ
  ̎ds֐ do_fork() ͉A\[XR[h
  kernel/fork.cɔ[߂Ă܂B

  ȉ̃XebvŎs܂B

  1. [Jϐretval-ENOMEMɃZbgBfork(2)V
     ^XN\̂̊蓖ĂɎsƂɃZbgerrno̒lɂȂ
     B

  2.  CLONE_PID  clone_flags ɃZbgĂꍇAĂяo
     AChXbh(u[ĝ)łȂAG[(-EPERM)ԂB
     ̃[UXbhCLONE_PIDclone(2)ɓnƂ͂łȂA
     ҂邱ƂłȂB
  3. current->vfork_sem (͎qɂČɃNA
     )BႦ΁ÃvO exec() Aexit(2) Ƃ̂悤
     ɁA sys_vfork() (clone_flags = CLONE_VFORK|CLONE_VM|SIGCHLD
     Ɋ֘A vfork(2) VXeR[) ɂAqvZX
     mm_release()s܂ŁAex~邽߂ɎgB

  4. V^XN\̂A[LeN`ˑalloc_task_struct()}N
     gĊ蓖ĂBx86 ł́AGFP_KERNEL Dx gfp ɂȂ
     Bꂪ fork(2) VXeR[x~ő̗RɂȂĂ
     B蓖Ăs΁A-ENOMEMԂB

  5. ݂̃vZX̃^XN\̂̑SĂ̒ĺA\̂̑ *p =
     *current ɂāAV̂փRs[B炭́Amemcpy
     ɒûׂB̌ŁAqɈpȂtB[h
     ́Alɐݒ肳B

  6. c̃R[hGgg\ł͂ȂƂA傫ȃJ[l
     bN擾B

  7. Ae[UĂꍇ (UID̍lɂāALinux
     ́AƂĂł͂ȂA̎邾̏\ȏ_Ă
     ) A[URLIMIT_NPROC\tg~bgzĂ邩ǂmF
     BzĂȂ玸s-EAGAINԂBzĂȂ΁A
     ^ꂽuid̃vZX̃JE^p->user->count1B

  8. AsVXeŜ̃^XNA\Ȓlł
     max_threads zĂꍇAs-EAGAINԂB

  9. oCiW[s̈Ɋ֘AĂꍇA֘AW[
     ̃t@XJE^𑝂₷B

  10.
     AsoCiW[ꂽoCitH[}bg
     ֘AĂꍇA֘AW[̃t@XJE^1
     B

  11.
     qusĂȂv(p->pid_exec = 0)ƃ}[NB

  12.
     quXbvsv(p->swappable = 0)ƃ}[NB

  13.
     qAu荞ݕsx~vԁA܂p->state =
     TASK_UNINTERRUPTIBLEɓ(TODO: ȂꂪŝH킽ɂ
     svɎv鄟폜ɂ́ALinus KvȂƔF߂Kv
     )B

  14.
     qp->flags clone_flags ̒lɂĐݒ肳Bʏ
     fork(2)̎́Ap->flags = PF_FORKNOEXECɂȂB

  15.
     qpid p->pid kernel/fork.c:get_pid()ɂ fast ASY
     gpāAݒ肳B(TODO: lastpid_lockXsbN̓__g
     ɂłBdo_fork()傫ȃJ[lbN̂Əget_pid()
     ΂get_pid()̃tO폜΃__gɂłBpb`
     Alan 2000N620ɑB̌tH[邱)

  16.
     do_fork()̎c̃R[h́Aq̃^XN\̂̎cB
     ŌɁAq̃^XN\̂pidhashnbV\ɃnbVAq͋N
     (TODO: wake_up_process(p)p->state = TASK_RUNNINGݒ肵A
     vZX runq ɉBāAdo_fork()̍ŏ̂ق
     p->stateTASK_RUNNINGɐݒ肷Kv͂炭Ȃ)B[
     ́Afork(2)ɂƂSIGCHLDӖAp->exit_signalclone_flags &
     CSIGNALɐݒ肷邱ƂƁAp->pdeath_signal0ɐݒ肷邱ƂłB
     pdeath_signaĺA(eʂȂǂ)vZXIWi̐euY
     vƂɎgAprctl(2)VXeR[PR_GET/SET_PDEATHSIG
     Đݒ/擾邱ƂłB(pdeath_signal̒ĺAprctl(2)
     [UԂ̃|C^A[MgoRĖ߂ƂƂ
     svcƎ咣邩Ȃ\߂ȂBAndries Brouwer
     }jAy[WXVƂ̂ŁACԂɍȂ
     ;)

     ̂悤Ƀ^XN܂BāA^XNI[ɂ́A
     @܂B

  1. exit(2)VXeR[𔭍sB

  2. ftHgŎʐ̃VOi͂B

  3. ̗OɂāAIɎʁB

  4. func == 1bdflush(2)Ă ( Linux ƓłA'update's
     /etc/inittabɎcĂ悤ȌÂfBXgr[VƂ̌݊
     ̂߂łB݂łupdate̎d́AJ[lXbhkupdate
     sĂ)B

  Linux ŃVXeR[Ă֐́Asys_̃vtBbNX
  Ă܂BÅ֐́AẴ`FbNA[LeN
  `Ɠ̏̓nɂĂ̂݊֐SĂAۂ̎d́Ado_
  ̂֐s܂B̂߁Asys_exit()ɂẮAdo_exit()
  ۂ̎ds߂ɌĂяo܂BȂAJ[l̑̕Ŏ
  ܁AĂdo_exit()ĂяoȂ΂ȂȂ
  ŁAsys_exit()ĂяoĂƂ낪󂯂܂B

  do_exit()֐́Akernel/exit.cɂ܂Bdo_exit()ɂẴ|Cg
  ƂẮA

  o  O[oJ[lbNgp(bN邪bNȂ)B

  o  schedule()ŌɌĂяoA߂邱Ƃ͂ȂB

  o  ^XNԂTASK_ZOMBIEɐݒ肷B

  o  0łȂ΁Acurrent->pdeath_signalɂAׂĂ̎qɒʒm
     B

  o  ecurrent->exit_signalɂĒʒmB͒ʏSIGCHLDɂȂB

  o  forkɂĊ蓖ĂꂽBI[vt@C
     ǁB

  o  lazy FPUXCb`OgA[LeN`̏ꍇ(ia64, mips, mips64)
     (TODO: sparc, sparc64'flags'폜) FPUI[i[Vbv(
     JgLĂjuȂvn߂Ƀn[hEGAv
     邱ƂsB

  2.3.  LinuxXPW[

  XPW[̎d́AJg CPU ւ̃ANZX𕡐̃vZXԂ
  ق邱Ƃɂ܂BXPW[́AuC̃J[lt@C
  vkernel/sched.cɎĂ܂B֘Âփb_t@Cł
  include/linux/sched.h́A(IɂԐړIɂ)SẴJ[
  l\[Xt@Cǂݍ܂܂B
  XPW[Ɋ֘A^XN\̂̃tB[hɂ́Â̂
  B

  o  p->need_resched: ̃tB[h́Aschedule()ű@vɋN
     ׂɃZbg܂B

  o  p->counter: ̃XPW[OXCXł̎s̎c̃NbN
     `bNŃ^C}ɂČB̒l0ȉɂȂƂ
     ́Ap->need_resched ݒ肳B͎gύXł邽߁Av
     ZX́uIDxvƌĂ΂邱ƂB

  o  p->priority: vZX̐ÓIȗDxłA悭gVXeR[
     nice(2)APOSIX.1bsched_setparam(2)A4.4BSD/SVR4
     setpriority(2)ɂĕύXB

  o  p->rt_priority: A^CDxB

  o  p->policy: XPW[O|V[łA^XNXP
     W[ÕNX\Bsched_setscheduler(2)VXeR[g
     ƂŁA^XÑXPW[ÕNXύX邱ƂłB
     肤lɂ́ASCHED_OTHER(`IUNIX̃vZ
     X)ASCHED_FIFO(POSIX.1b FIFO A^CvZX)SCHED_RR(POSIX
     EhrA^CvZX)B́ASCHED_YIELD
     OR邱ƂłAƂsched_yield(2)VXeR[Ăяo
     ƂɂāAvZX CPU 邱ƂɂƂƂł
     BFIFOA^CvZX a) I/OubN邩Ab) I
      CPU 邩Ac) ̍p->rt_prioritylA^C
     vZX犄荞܂邩Aꂩ܂ŎsB

  schedule()֐́A|AɕGłAXPW[̃ASY
  ͒PłB֐GȂ̂́A3̃XPW[OASY
  ɎĂ̂ƓɁASMP ̃fP[gȎdlĂ邩
  B

  炩Ɂuʂȁvgotoschedule()ɂ܂Ai386ňԍœK
  ꂽR[h𐶐邽߂łBAXPW[2.4ŊS(
  J[l̑̕l)܂B̂߁Aȉ̋c_2.2₻
  ȑÕJ[lɂ͓Ă͂܂܂B

  ł͏ڍׂɊ֐Ă܂傤B

  1. current->active_mm == NULLȂAȂɂBJg̃v
     ZX́AJ[lXbh(current->mm == NULL )łƂĂA
     p->active_mmɎĂȂ΂ȂȂB

  2. tq_scheduler^XNL[Ɏŝ΁A܂
     B^XNL[͊֐̎sx点ăXPW[sJ[l
     ̎dg݂񋟂̂łB̏ڍׂ͑̏͂ŐB

  3. [Jϐprevthis_cpuAꂼꌻ݂̃^XNƌ݂ CPU 
     B

  4. schedule()(oOɂ)荞݃nhNĂȂ
     `FbNBȂJ[lpjbNɂȂB

  5. O[oJ[lbNB

  6. \tg荞݋@\oRōsƂ΁AŎsB

  7. [J|C^struct  schedule_data *sched_dataACPU
     (LbVCs|邽߃LbVCɃAC
     )XPW[Of[^̈w悤ɂB
     ́Alast_scheduleTSClŌɃXPW[ꂽ^XN\̂ւ
     |C^ȂĂB(TODO: sched_data SMP ̎̂ݎg
     AȂinit_idle() UPłĂlɏŝ?)

  8. runqueue_lockXsbN擾Bspin_lock_irq()g
     ̂́Aschedule()̒ŁA荞݉ɂȂĂ邱Ƃۏ؂邽߂
     BāArunqueue_lockƂ
     ́A(spin_lock_irqsave/restorë) saving/restoring eflagsg
     ̂ł͂ȂAPɍēxLɂ邾ł悢B

  9. ^XNԋ@B: ^XNTASK_RUNNINGԂɂ΁Â܂܂ɂ
     BTASK_INTERRUPTIBLEԂłAVOiۗĂ
     ΁ATASK_RUNNINGԂֈڍsBȊȌꍇ́Arunqueue
     B

  10.
     (ƂXPW[₷)next CPU ł̃ACh^
     XNɂBǍ̃ObhlX́Â̂
     Ȃ悤ɁAƂĂႢl(-1000)ƂȂB

  11.
     prev(Jg)̃^XNTASK_RUNNINGԂł΁AJg
     ObhlX̃ObhlXƓɐݒ肷BACh^XNXP
     W[₷Ȃ悤B

  12.
     āArunqueue𒲂ׁACPUŃXPW[邱Ƃ\Ȋev
     ZX̃ObhlXJg̒lƔrBāAƂOb
     hlXvZXBŁÁu CPU ŃXPW[
     邱Ƃ\ȁvƂl𖾊mɂƁAUP ł́Arunqueue 
     evZXXPW[\łBSMP ɂẮAłɑ CPU
     ős\ɂȂĂȂvZXXPW[łBObhl
     Xgoodness()Ƃ֐ɂvZBA^CvZX
     ObhlXł͔ɍ(1000 + p->rt_priority)邱ƂŏB
     1000 傫ƂŁASCHED_OTHERł͂ȂvZXƂۏ
     ĂBđ̂傫p->rt_priorityA^Cv
     ZXƂłB

     vZX̃^CXCX(p->counter)IƂ́Agoodness ֐
      0 ԂBA^Cł͂ȂvZXł́AObhlX̏l
     p->counter ɐݒ肳邽߁Ałɂ΂炭̊ CPU Lv
     ZX́A CPU 𓾂邱ƂȂȂB܂ΘbIvZX́ACPU
     蓖ĂƂĂ܂vZXD悳BA[LeN
     `ŗL̒萔PROC_CHANGE_PENALTÝuCPU Ƃ̖ړxv悤
     (܂A CPU ̃vZXD悳)ŁA̓Jg
     active_mmĂvZXA([UjAhXԂȂ(
     J[lXbĥ悤)vZXɎ኱̗Dx^B

  13.
     AObhlX݂̌̒l 0 ̂Ƃ́AvZX̃Xg̑S
     (runqueueɂ̂ł͂Ȃ)A̓IȗDxP
     ȃASYɂČvZB

  ______________________________________________________________________

  recalculate:
          {
                  struct task_struct *p;
                  spin_unlock_irq(&runqueue_lock);
                  read_lock(&tasklist_lock);
                  for_each_task(p)
                          p->counter = (p->counter >> 1) + p->priority;
                  read_unlock(&tasklist_lock);
                  spin_lock_irq(&runqueue_lock);
          }
  ______________________________________________________________________

  ČvZsOrunqueue_lock邱Ƃɒڂ悤BSẴvZ
  X̔z邽߁AԂKvƂ邩炾BCPU ČvZ
  Ă邻̊ԂɁAschedule() CPU ɂČĂ΂A CPU ɂƂ
  \ɃObhlXǂvZXIԂƂłBA͖炩
  ƖĂB( CPU )ƂǂObhlX
  vZXIłԂɁA CPU ŎsĂ schedudle()
  AIDxČvZ邱ƂłĂ邩炾B

  14.
     ̎_ŁAnextXPW[^XNwĂÂ
     next->has_cpu 1 next->processorthis_cpuɏĂ邱
     młBrunqueue_lock͂ŉłB

  15.
     ^XNɖ߂ĂȂ(next == prev)APɃO[oJ[
     lbNĎ擾ԂB܂ASẴn[hEGAx(WX
     ^AX^bNȂ) VM ֘A(XCb`y[WfBNgAactive_mm
     ČvZȂ)̂̂̓XLbvB

  16.
     }Nswitch_to()̓A[LeN`LłBi386ł́A a)FPU
     nhOAb) LDT nhOAc) ZOgWX^̃[
     hAd)TSS̃nhOAe) fobOWX^̃[hɊ֌W
     B

  2.4.  Linuxł̃NXg̎

  EGCgL[̎ɍsOɁALinuxW̃_uNXg̎
  nmȂ΂Ȃ܂BEGCgL[(Linux̑̂̂Ɠlj́A
  ̎ǂg܂Ainclude/linux/list.h Ƃ֘AĂ邱
  ƂAW[SŁulist.h ̎vƂĂ΂܂B

  ł̊bIȃf[^\̂́Astruct list_headłB

  ______________________________________________________________________
  struct list_head {
          struct list_head *next, *prev;
  };

  #define LIST_HEAD_INIT(name) { &(name), &(name) }

  #define LIST_HEAD(name) \
          struct list_head name = LIST_HEAD_INIT(name)

  #define INIT_LIST_HEAD(ptr) do { \
          (ptr)->next = (ptr); (ptr)->prev = (ptr); \
  } while (0)

  #define list_entry(ptr, type, member) \
          ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

  #define list_for_each(pos, head) \
          for (pos = (head)->next; pos != (head); pos = pos->next)
  ______________________________________________________________________

  ŏ 3 ̃}Nnextprev|C^gw悤ɂāA󃊃X
  ĝłBႦ΁ALIST_HEAD_INIT() ́A錾ɍ\̂
  vf邽߂ɎgA2ڂ̓X^eBbNϐ̏s
  ŁA3ڂ͊֐̒Ŏgƌ悤ɁAǂꂪǂŎg邩
  ́A C ̍\̐񂩂炩łB

  }Nlist_entry()͂ꂼ̃Xgvfւ̃ANZX񋟂܂B
  ΁A (fs/file_table.c:fs_may_remount_ro()̗):

       ______________________________________________________________________
       struct super_block {
          ...
          struct list_head s_files;
          ...
       } *sb = &some_super_block;

       struct file {
          ...
          struct list_head f_list;
          ...
       } *file;

       struct list_head *p;

       for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
            struct file *file = list_entry(p, struct file, f_list);
            do something to 'file'
       }
       ______________________________________________________________________

  list_for_each()}N̎g̗ǂႪA傤ǒڂĂXP
  W[̂Ȃ́AƂObhlXvZXTrunqueue
  镔ɂ܂B

  ______________________________________________________________________
  static LIST_HEAD(runqueue_head);
  struct list_head *tmp;
  struct task_struct *p;

  list_for_each(tmp, &runqueue_head) {
      p = list_entry(tmp, struct task_struct, run_list);
      if (can_schedule(p)) {
          int weight = goodness(p, this_cpu, prev->active_mm);
          if (weight > c)
              c = weight, next = p;
      }
  }
  ______________________________________________________________________

  ŁAp->run_list́Atask_struct\̂̒struct list_head
  run_listƂĐ錾Ă܂BāAXg̃AJ[񋟂܂B
  vfXg폜A邢͒ǉ(Xg̐擪ɂAɂ)
  ꍇɂ́Alist_del()/list_add()/list_add_tail()}NɂĎs
  ܂Bȉ̗́Arunqueueփ^XNǉэ폜łB

       ______________________________________________________________________
       static inline void del_from_runqueue(struct task_struct * p)
       {
               nr_running--;
               list_del(&p->run_list);
               p->run_list.next = NULL;
       }

       static inline void add_to_runqueue(struct task_struct * p)
       {
               list_add(&p->run_list, &runqueue_head);
               nr_running++;
       }

       static inline void move_last_runqueue(struct task_struct * p)
       {
               list_del(&p->run_list);
               list_add_tail(&p->run_list, &runqueue_head);
       }

       static inline void move_first_runqueue(struct task_struct * p)
       {
               list_del(&p->run_list);
               list_add(&p->run_list, &runqueue_head);
       }
       ______________________________________________________________________

  2.5.  EGCgL[

  vZXJ[lɈ˗Ƃݕs\ł邪Aɉ\ƂȂ鎖
  łȂAvZX͋x~ԂւƓAv
  ȂƂɋN܂B̎gJ[l̃JjŸuE
  GCgL[vłB

  Linux ̎ł́ATASK_EXCLUSIVEtOgNZ}eBNX
  ܂BEGCgL[ɂāAwell-knownL[gĒP
  sleep_on/sleep_on_timeout/interruptible_sleep_on/interruptible_sleep_on_timeout
  gƂł܂Ag̃EGCgL[`AɎg
  /폜邽߂ add/remove_wait_queue gpāAKvɋN邽
  wake_up/wake_up_interruptible gp邱Ƃł܂B

  ŏ̃EGCgL[̎g̗Ƃ
  ́A(mm/page_alloc.c:__alloc_pages()) y[WAP[^ 
  (mm/vmscan.c:kswap()) kswapd J[lf[̊Ԃɂ
  Amm/vmscan.c Œ`EGCgL[kswapd_waitɂ鑊ݍp
  ܂Bkswapdf[͂̃L[ŋx~Ay[WAP[^y[
  WĂKvł܂ŋN邱Ƃ͂܂B

  IȃEGCgL[̗pɂ́A read(2)VXeR[Ńf[^v
  郆[UvZXƁAf[^񋟂邽߁A荞݃ReLXgős
  J[l̊Ԃ̑ݍp܂B荞݃nh͈ȉ̂悤
  ȂĂ܂ (drivers/char/rtc_interrupt()ȗ)B

       ______________________________________________________________________
       static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);

       void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
       {
               spin_lock(&rtc_lock);
               rtc_irq_data = CMOS_READ(RTC_INTR_FLAGS);
               spin_unlock(&rtc_lock);
               wake_up_interruptible(&rtc_wait);
       }
       ______________________________________________________________________

  Ŋ荞݃nh́AfoCXɓLI/O |[gǂݎ
  (CMOS_READ() }N͕ outb/inbɂȂ܂)ƂŃf[^擾
  Artc_wait EGCgL[ŋx~̂̂N܂B

  ______________________________________________________________________
  ssize_t rtc_read(struct file file, char *buf, size_t count, loff_t *ppos)
  {
          DECLARE_WAITQUEUE(wait, current);
          unsigned long data;
          ssize_t retval;

          add_wait_queue(&rtc_wait, &wait);
          current->state = TASK_INTERRUPTIBLE;
          do {
                  spin_lock_irq(&rtc_lock);
                  data = rtc_irq_data;
                  rtc_irq_data = 0;
                  spin_unlock_irq(&rtc_lock);

                  if (data != 0)
                          break;

                  if (file->f_flags & O_NONBLOCK) {
                          retval = -EAGAIN;
                          goto out;
                  }
                  if (signal_pending(current)) {
                          retval = -ERESTARTSYS;
                          goto out;
                  }
                  schedule();
          } while(1);
          retval = put_user(data, (unsigned long *)buf);
          if (!retval)
                  retval = sizeof(unsigned long);

  out:
          current->state = TASK_RUNNING;
          remove_wait_queue(&rtc_wait, &wait);
          return retval;
  }
  ______________________________________________________________________

  rtc_read() ŋNĂ鎖Ƃ̂́A

  1. EGCgL[̗vfJgvZX̃ReLXgw悤錾
     B

  2. ̗vf rtc_wait EGCgL[ɒǉB

  3. ݂̃ReLXgɁAx~ƂɍăXPW[Ȃ
     Ӗ TASK_INTERRUPTIBLẼ}[NÂB

  4. f[^݂Ȃǂ`FbNB݂ȂA
     făf[^[Uobt@ɃRs[AgTASK_RUNNINGƃ}[N
     āAgEGCgL[폜āAԂB

  5. f[^Ȃ΁A[UmubLO I/O w肵ǂ
     `FbNAȂAEAGAIN(́AEWOULDBLOCKƓ)G[
     IB

  6. ł܂AVOiۗĂȂ`FbNBۗ
     Ă΁AũC[vɁAKv΃VXeR[
     X^[g悤m点BuKv΁vƂ́Asigaction(2)VX
     eR[Ŏw肳VOi̐̏ڍׂӐ}ĂB

  7. āAuswitch outv܂A荞݃nhɋN܂ŋx~
     ԂɂȂBgTASK_INTERRUPTIBLEɃ}[NȂƁAXP
     W[̓f[^LɂȂ葁XPW[邽߁AsKv
     ̌ɂȂB

  ܂AEGCgL[p邱ƂŁApoll(2)VXeR[̎ނ
  eՂɂȂĂ邱ƂwEĂ܂傤B

       ______________________________________________________________________
       static unsigned int rtc_poll(struct file *file, poll_table *wait)
       {
               unsigned long l;

               poll_wait(file, &rtc_wait, wait);

               spin_lock_irq(&rtc_lock);
               l = rtc_irq_data;
               spin_unlock_irq(&rtc_lock);

               if (l != 0)
                       return POLLIN | POLLRDNORM;
               return 0;
       }
       ______________________________________________________________________

  SĂ̎d́AfoCXˑ֐poll_wait()ɂčs܂B
  ́AKvȃEGCgL[̑s܂BXȂ΂ȂȂ
  ́AfoCXL̊荞݃nhɂċNׂEGCgL[w
  邱ƂłB

  2.6.  J[l^C}

  āA̓J[l^C}ɒڂ܂傤BJ[l^C}Ƃ́A̓
  ̎ɁÅ֐(u^C}[nhvƌĂ΂)̎ss킹
  ߂ɂ̂łBȃf[^\̂́Astruct timer_listł
  Ainclude/linux/timer.hŒ`Ă܂B

       ______________________________________________________________________
       struct timer_list {
               struct list_head list;
               unsigned long expires;
               unsigned long data;
               void (*function)(unsigned long);
               volatile int running;
       };
       ______________________________________________________________________

  listtB[h͓̃XgւƃN邽߂̂̂ŁAtimerlist_lock
  XsbNɂی삳Ă܂BexpirestB[h́Afunctionn
  hdatap[^ƂēnNƂjiffies̒l
  BrunningtB[h́A^C}nhݑ CPU œ삵Ă邩
  eXg邽߂ SMP ɂėp܂B

  ֐add_timer()ƁAdel_timer()́A^ꂽ^C}̃Xgւ̒ǉȂ
  тɍ폜s܂B^C}̎ԂIƁAIɍ폜܂B^
  C}gOɁAKinit_timer()֐ɂďȂ΂Ȃ
  BāAǉOfunctionexpirestB[hKݒ肵Ȃ
  Ȃ܂B

  2.7.  {gn[t

  荞݃nhsdAɍs(Ⴆ΁A荞݂ւ̔
  AԂ̍XVȂǂ)dƁA荞݂L(f[^̌㏈)ɂȂĂ
  AŏΗǂ(f[^̌㏈̎{Af[^҂Ă
  vZXNȂ)Ƃ2ɕ̂ɂȂĂ邱ƂAX
  ܂B

  {gn[t́AJ[l^XN̎słÂ@\ŁALinux
  1.x̂Ƃ炠܂BLinux 2.0ɂȂāȀ͂Ŏ舵u^XN
  L[vƂV@\܂B

  {gn[tglobal_bh_lockXsbNɂăVACY܂B
  ܂xɂꂩCPUŎsł̂́A̃{gn[t̂
  łƂƂłBnhs悤ƂƂAglobal_bh_lock
  LłȂ΁A{gn[t͎s̈(܂XPW[
  )܂BāAglobal_bh_lockŃrW[[v邱Ƃ邽ߏ
  ͌p܂B

  ݁AS32̃{gn[to^Ă܂B{gn[t𑀍
  邽߂ɕKvƂȂ֐́Aȉ̂悤ɂȂ܂(ׂăW[
  Ă܂)B

  o  void init_bh(int nr, void (*routine)(void)): routineŎw{
     gn[tnhXbgnr֓BXbg
     include/linux/interrupt.hɁAXXXX_BȞ`(Ⴆ΁ATIMER_BH
     TQUEUE_BĤ悤)񋓂ĂȂ΂ȂȂBʏATuVXe
     ̏[`(W[̏ꍇɂinit_module())́Å֐
     gĕKvȃ{gn[t𓱓B

  o  void remove_bh(int nr): init_bf()̋tsB܂AXbgnr
     ɓꂽ{gn[t폜Bł̓G[`FbN͍s
     ȂB̂߁AႦ΁Aremove_bh(32)̓VXepanic܂oops
     ȂBʏATuVXẽN[Abv[`(W[̏
     Acleanup_module())ÃTuVXeōėpł悤A
     ֐Xbg邽߂ɎgpB(TODO: VXȇSĂ̓o^
     ꂽ{gn[tA/proc/bottom_halvesɃXgAbvꂽǂ
     낤? ́Ablobal_bh_lockIɓǂݏȂ΂Ȃ
     ƂƂӖ)

  o  void mark_bh(int nr): Xbgnr̃{gn[tɎs̈B
     ʏA荞݃nh͂̃{gn[t(̖OR!)
     uSȎvɎs悤B

  {gn[t́AO[obNꂽ^XNbgłBŁu{g
  nh͂ŝHvƂ́A{́u^XNbg͂
  ŝ?vƂ̂{Ȃ̂łB́Aa) eschedule()
  b)entry.S̊e荞/VXeR[̃^[pX̓JłB(TODO:
  ̂߁Aschedule()̏ꍇ͖{ɒx̂łB̔ɒxx
  荞݂ǉ悤Ȃ̂łBȂAschedule()handle_softirq
  xSɎ菜Ȃ̂?)

  2.8.  ^XNL[

  ^XNL[͌Â{gn[t̃_Ci~bNȊgƂčl܂B
  ۂ̂ƂA\[XR[hł́AuVv{gn[tƂĎQƂ
  Ƃ܂B̓Iɂ́AO͂ŎグÂ{gn[t
  ɂ́AɎ悤Ȑ܂B

  1. ߂ꂽ(32)݂ł܂B

  2. e{gn[t͈̃nh֐Ƃ֘AÂ܂B

  3. {gn[t́AubNoȂ悤ɁAĂXsbN
     ܂B

  ŁA^XNL[ɂCӂ̐̊֐ȂAŎXƏł
  悤ɂ܂B DECLARE_TASK_QUEUE }NgĐV^XNL[
  쐬ƁAqueue_task()֐gāÃL[ւƃ^XN߂邱
  ł܂BāA^XNL[run_task_queueɂď܂B
  g̃^XNL[쐬(āA蓮ŏ
  ɁjALinux ɂ炩ߏꂽAǂmꂽŏ^XN
  L[gƂł܂B

  1. tq_timer: ^C}̃^XNL[Be^C}荞ݖ tty foCX
     Ƃ(I[vԂ̃^[~ifoCXN[YȂ͉
     鎞)ɎsB^C}nh荞݃ReLXgŎs
     Ƃ́Atq_timer^XN荞݃ReLXgŎs邽߁A
     ubNłȂB

  2. tq_scheduler: XPW[ɂ(tq_timer l tty Ƃ
     )XPW[^XNL[BXPW[ăXPW[
     vZX̃ReLXgŎs邽߁Atq_scheduler ^XN
     肽ƂłłB܂AubNăvZX̃ReL
     Xg̃f[^gp(肽ǂ͕ʂƂ)ȂǂłB

  3. tq_immediate: ͖{̓{gn[tIMMEDIATE_BHłÂ
     hCoqueue_task(task, &tq_immediate) ƁAĊ荞݃Re
     LXgŏmark_bh(IMMEDIATE_BH)sB

  4. tq_disk: ۂ̗vJn邽߁A჌xubNfoCX̃ANZ
     X(RAID)ɂgB̃^XNL[̓W[ɃGLX|[
     g邪A݌v̖̓ړIĎgȂB

  hCog̃^XNL[gȂAȉ̏ꍇāA
  L[邽߂run_tasks_queue()ĂԕKv͂܂B

  ^XNL[tq_timer/tq_scheduler ̂ʏ̏ꏊłȂO
  ̏ꏊ(ƂẮAttyfoCX̃N[Y)łs闝ŔAhC
  oL[Ƀ^XNXPW[ƂÃ^XNӖ̂̓f
  oCX̓̃CX^XLłƂ(ʏ̓AvP[VN
  [Y܂)Ȃ̂lƎƖ炩ł傤B̂߁AhCo
  run_task_queueĂŁAg(̃hCo)L[ɂꂽ^XN
  tbVKv܂B́AŎs邱Ƃł悤ɂ
  邱ƂӖłB܂A֘Af[^\͑̃CX^X
  ɂꂽėpƂƂłBꂪAꂼ^C}
  荞݂schedule()̑tq_timertq_schedulerrun_task_queue()
  闝RɂȂĂ܂B

  2.9.  ^XNbg

  쐬B̃rWŋLqB

  2.10.  \tg荞

  쐬B̃rWŋLqB

  2.11.  VXeR[i386ł͂ǂ̂悤ɎĂ邩?

  o  lcall7/lcall27 R[Q[g

  o  int 0x80 \tgEGA荞

  UNIXnOS(Solaris, Unixware 7 Ȃ)̃oCiłlcall7JjY
  gĂ܂AlCeBu Linux vO int 0x80 gĂ
  B'lcall7'̖ÓAjIȉ߂łB́Alcall27(Ⴆ
  Solaris/x86)gpĂ邪Anh֐lcall7_funcƌĂ΂Ă
  łB

  VXeu[gƂAIDTݒ肷֐
  arch/i386/kernel/traps.c:trap_init() Ă΂A(type 15, dpl 3 )xN
  ^ 0x80 Aarch/i386/kernel/entry.S̃VXeR[GgAhX
  悤ɐݒ肵܂B

  [UԂ̃AvP[VVXeR[śAWX^
  ɓāA'int 0x80' ߂s܂B́AJ[l[hɃgb
  vAvZbTentry.S̃VXeR[Gg|CgւƃW
  v܂B́Â悤ȂƂs܂B

  1. WX^ۑB

  2. %ds  %es  KERNEL_DS ɐݒ肷B̂߁AQƂSẴf[^(
     ƊÕZOg)̓J[lAhXԂɂȂB

  3.  %eax ̒lNR_syscalls( 256) 傫ꍇ
     ́AENOSYS G[ŎsB

  4. ^XNptraced Ă(tsk->ptrace & PF_TRADESYS )́A
     ʂȏsB strace (SVR4łtruss(1))̂悤ȃvO
     fobKT|[g邽߂łB

  5. sys_call_table+4*(%eax  syscall_number)ĂԁB̃e[u͓
     t@C(arch/i386/kernel/entry.S)ŏĂAeX̃VXe
     R[nhwĂBLinux ɂẮAnhɂ͒ʏA
     Ⴆ sys_opensys_exit̂悤 sys_ƂvtBbNX
     B C VXeR[nhSAVE_ALLi[X^bN
     oB

  6. ``system call return path''ɓBint 0x80 łȂAlcall7,
     lcall27łg߁Aʂ̃xɂȂĂB́A({gn[t
     )^XNbg̎舵Aschedule()Kvǂ
     (tsk->need_resched != 0) mFAVOiۗĂȂ
     mFAẴVOi肷邱ƂɊ֘A
     B

  Linux  VXeR[ 6 ܂ł̈T|[gĂ܂B
  %ebx, %ecx, %edx, %esi, %edi (шꎞIɎg
  %edpBasm-i386/unistd.h_syscall6()Q)ɓēn܂BVXe
  R[ԍ %eax œn܂B

  2.12.  Ag~bNȑ

  2̃^CṽAg~bNȑ삪܂Brbg}bvatomic_t łB
  rbg}bv́A傫ȏWu蓖āvuv̒PʂŁAeP
  ʂԍŎw肳AႦ΃t[ inodet[ubN̂悤ȃR
  Zvgێ̂ɂƂĂ֗łB͒PȃbNɍLg
  Ă܂BႦ΃foCX̃I[vrIɍs悤ɂ邽߂Ɏg
  ܂B̗́Aarch/i386/kernel/microcode.cɌ邱Ƃł܂B

       ______________________________________________________________________
       /*
        *  Bits in microcode_status. (31 bits of room for future expansion)
        */
       #define MICROCODE_IS_OPEN       0       /* set if device is in use */

       static unsigned long microcode_status;
       ______________________________________________________________________

  BSS Linux ŖIɃ[N[悤 microcode_status 0ɏ
  Kv͂܂B

       ______________________________________________________________________
       /*
        * We enforce only one user at a time here with open/close.
        */
       static int microcode_open(struct inode *inode, struct file *file)
       {
               if (!capable(CAP_SYS_RAWIO))
                       return -EPERM;

               /* one at a time, please */
               if (test_and_set_bit(MICROCODE_IS_OPEN, &microcode_status))
                       return -EBUSY;

               MOD_INC_USE_COUNT;
               return 0;
       }
       ______________________________________________________________________

  rbg}bv̑́A

  o  void set_bit(int nr, volatile void *addr): addrŎrbg}b
     vnr̃rbgZbgB

  o  void clear_bit(int nr, volatile void *addr): addrŎrbg
     }bvnrrbgNAB

  o  void change_bit(int nr, volati.e void *addr): addrŎrbg
     }bvnrrbg𔽓](NAĂ΃ZbgAZbgĂ
     NA)B

  o  int test_and_set_bit(int nr, volatile void *addr): Ag~bNnr
     rbgZbgAÂrbg̒lԂB

  o  int test_and_clear_bit(int nr, volatile void *addr): Ag~bNnr
     rbgNAAÂrbg̒lԂB

  o  int test_and_change_bit(int nr, volatile void *addr): Ag~bN
     nrrbg𔽓]AÂrbg̒lԂB

  ̑́ALOCK_PREFIX }NgĂ܂B̃}N SMP
  J[lɂăoX̃bNsړƂĕ]܂AUP
  J[lł͉܂BɂāASMP ł̃Ag~bNȃANZ
  Xۏ؂Ă܂B

  Ƃɂ̓rbg삪sւȏʂ܂Ȁꍇ͎ZpZgK
  v܂BZAZACNgAfNgȂǂłB(inode
  ̂悤)QƃJE^T^IȗłB̋@\atmic_tf[^^Cv
  ȉ̑ŎĂ܂

  o  atomic_read(&v): atomic_tϐt̒lǂݍށB

  o  atomic_set(&v, i): atomic_t ϐ v 𐮐l i ɐݒ肷B

  o  void atomic_add(int i, volatile atomic_t *v): li v Ŏ
     Ag~bNϐ̒lɉZB

  o  void atomic_sub(int i, volatile atomic_t *v): li v Ŏ
     Ag~bNϐ̒l猸ZB

  o  int atomic_sub_and_test(int i, volatile atomic_t *v): li v
     ŎAg~bNϐ̒l猸ZǍʂ0̂Ƃ 1 
     AȊOł 0 ԂB

  o  void atomic_inc(volatile atomic_t *v): l 1 CNgB

  o  void atomic_dec(volatile atomic_t *v): l 1 fNgB

  o  int atomic_dec_and_test(volatile atomic_t *v): lfNg
     BāAʂ0Ȃ1ԂAȊOȂ0ԂB

  o  int atomic_inc_and_test(volatile atomic_t *v): lCNg
     BāAʂ0Ȃ1ԂAȊOȂ0ԂB

  o  int atomic_add_negative(int i, volatile atomic_t *v): i v̒lɉ
     ZBāAʂȂ1ԂAʂ0ȏł0
     B̑̓Z}tH̎ɗpĂB

  2.13.  XsbNAǂݏXsbNArbO[_[XsbN

   Linux (OI 90 N̏)AJ҂́AقȂ^̃ReL
  Xg̊ԂA CPU ɂ铯^̃ReLXgł邪C
  X^XԂł̋Lf[^̃ANZXɊւÓTIɒʂĂ܂
  B

  1995 N 11  15 ɁASMP T|[g(IWĩpb` N 10 
  1.3.37 ɑ΂̂ł) Linux 1.3.42 Œǉ܂B

  R[h̃NeBJ̈悪vZXReLXgƊ荞݃ReLXg
  Ŏs邱Ƃl̂ŁAUPcli/sti߂gĕی삷
  @́A

  ______________________________________________________________________
  unsigned long flags;

  save_flags(flags);
  cli();
  /* critical code */
  restore_flags(flags);
  ______________________________________________________________________

  ̂悤ɂȂ܂B

  ꂪ UP OKƂĂA SMP ł͖炩ɈӖ܂BR[
  hV[PX CPU œɎs邩mȂłB
  āAcli()͌X CPU ł̊荞݃ReLXg̋̕ی삵
  Ȃ߁AقȂ CPU ŎsReLXgԂ̋̕ی
  ɂ͑SȂȂ̂łBŃXsbNLpɂȂ܂B

  3 ̃^CṽXsbN܂Boj({)AǂݏArbO
  [_[ XsbNłBǂݏXsbŃuǂގ҂ď
  ҂Ȃv悭X̏ꍇɗp܂B̗ƂẮAo^
  t@CVXẽXg(fs/super.cQ)ւ̃ANZX܂BX
  ǵAfile_systems_lockǂݏXsbNɂی삳At@CV
  Xe̓o^/̍ۂɂrIȃANZXs܂BASĂ
  vZX/proc/filesystemsǂ߂܂Asysfs(2)VXeR[g
  āAt@CVXe̓ǂݎpANZXsƂł̂łB
  ̂ƂAǂݏXsbNgۂɋC_ɂȂĂ܂B
  ݏXsbNɂāAɕ̓ǂݎ肪ł邩AP̏
  ݂āA̓ǂݎ肪łȂ󋵂ɂȂ܂BƂ͂̂́A
  ݎ҂bN擾悤ƂĂԁAVǂݎ҂bN
  擾łȂȂA܂蕡̓ǂݎ҂ɂ鏑ݎ҂̋Qɂ
  āALinux ĂȂA͗ǂƂƂ܂B
  ҂bN擾悤ƂĂԂ́Aǂݎ҂ubNȂ
  ΂ȂȂƂӖĂ܂B

  ݂͌̂Ƃł͂ȂACȂ΂ȂȂƂǂ
  炩ł͂܂BtɂƁAǂݎ҂͏ɔɒZԂ
  bN擾Ă΁Aݎ҂rIԊԊuŃbN擾
  ĂԂɖ{Ɍ͊Ă܂Ƃ̂? ƂƂłB

  rbO[_XsbŃAǂݏXsbNɁAɌyǍ݃A
  NZX֋œK̂ŁA݃ANZXɂ̓yieBۂ
  Ă܂BrbO[_XsbN͌ꂽ͈́A݂2Ŏg
  Ă܂B sparc64 (global irq) ł̂ݎgA̓lb
  g[NX^bNłBANZXp^[2̌^̂ǂɂĂ
  ܂Ȃꍇł́A{XsbNgĂ܂Bǂ̎ނ̃Xsb
  NێĂꍇłubN邱Ƃ͂ł܂B

  v[A_irq()A_bh()ƁAXsbNɂ3ނ܂B

  1. v[spin_lock()/spin_unlock(): 荞݂ɕsɂ邩A
     荞݃ReLXgƋȂƂĂ(ႦΊ荞݃n
     h)ȂAgƂłB݂ CPU ̊荞ݏ
     ɂ͐G邱ƂȂB

  2. spin_lock_irq()/spin_unlock_irq(): 荞݂ɗLȂ炱
     o[W̃XsbNgƂłB͒PɌ݂ CPU
     ̊荞݂(bN)ɂA(AbNɁjēxLɂB
     Ƃ΁Artc_interrupt()spin_lock(&rtc_lock)(荞݂͊荞
     nh̒ł͏ɖ)g߁Artc_read()
     spin_lock_irq(&rtc_lock)(read荞݂͏ɗLjgĂ
     Brtc_read()spin_lock_irq()gAėpI
     spin_lock_irqsave()gȂ̂́ASẴVXeR[荞݂
     ɗLɂȂĂ邩łB

  3. spin_lock_irqsave()/spin_unlock_irqrestore(): 荞ݏ󋵂
     ȂƂɎgAŋ̌`B荞݂ɂȂꍇłȂA
     荞݂SsȏꍇɂgB܂A荞݃nhN
     eBJR[hsȂꍇɂ́Ag|Cg͂ȂƂ
     ƂB

  荞݃nhȂ΁Afspin_lock()g܂B
  gƂɁA荞݂CPUŔƁAiɃbN҂
  Â邽߂łB荞܂Ă郍bN擾nh́A荞
  nh珈ԂĂ܂ŁApłȂ߂łB

  [UvZX̃ReLXgƊ荞݃nhƂŋLf[^\
  ɃANZXƂɂ́AXsbNƂǂgĂ܂B

       ______________________________________________________________________
       spinlock_t my_lock = SPIN_LOCK_UNLOCKED;

       my_ioctl()
       {
               spin_lock_irq(&my_lock);
               /* critical section */
               spin_unlock_irq(&my_lock);
       }

       my_irq_handler()
       {
               spin_lock(&lock);
               /* critical section */
               spin_unlock(&lock);
       }
       ______________________________________________________________________

  ̗ɂẮAL܂B

  1. T^IȃhCoƂ@(lƕԂlmɏȗĂ
     )ioctl() ɂvZX̃ReLXgł́AKspin_lock_irq()
     gȂ΂ȂȂB́AfoCXioctl()ĂяosĂ
     Ԃ́A荞݂ɗLɂȂĂ邽߂łB

  2. (l͖mɏȗĂ)my_irq_handler()ɂĕ\銄
     ݃ReLXgł́Aplain spin_lock() form gƂłB
     ́A荞݃nhł́A荞݂͖ɂĂ邽߂ł
     B

  2.14.  Z}tHƓǂݏZ}tH

  ܁ALf[^\̂ɃANZXƂɁA̎subNȂ
  ΂ȂȂƂ܂BƂ΃f[^[UԂփRs[ꍇ
  ȂǂłBLinux ɂ邱̂悤ȏꍇɎgpł郍bN̊{@\Ƃ
  ăZ}tHƌĂ΂̂܂BZ}tHɂ2̃^CvA
  {Z}tHƓǂݏZ}tHƌĂł܂BZ}tH̏lɂA
  ݎs(l1)ɂA蕡GȃANZX̃^Cv񋟂邽߂ɂg
  Ƃł܂B

  ǂݏZ}tHƊ{̃Z}tHƂ̈Ⴂ́AǂݏXsbNƊ{
  ̃XsbN̑Ɠl̂̂ɂȂĂ܂Bɕ̓ǂ
  ƈ̏̂ɑ΂āA͏݂̂Ԃ͓ǂݏo
  bN̂ɂȂ܂B܂A肪SĂ̓ǂݎubN
  A肪҂ԂɂԁAVǂݎ̓ubN܂B

  lɁAfdown()/up()̑down/up_interruptible()g
  ƁAdown_interruptible()̕Ԃl`FbN邱ƂŁA{Z}tH
  ͊荞݂\ɂȂ܂B삪荞܂ꂽȂ΁AԂl0
  OɂȂ܂B

  NeBJR[h̃TuVXe⃂W[o^関m̊
  Ăяo󋵂ł́AT^Iɂ͌ݎsɃZ}tHgƂɂ
  ܂B܂AĂяo挱IɊ֐ubN邩ǂm邱
  ƂłȂꍇłB

  Z}tH̊ȒPȗ́Agethostname(2)/sethostname(2)VXeR[
  kernel/sys.cɂ܂B

       ______________________________________________________________________
       asmlinkage long sys_sethostname(char *name, int len)
       {
               int errno;

               if (!capable(CAP_SYS_ADMIN))
                       return -EPERM;
               if (len < 0 || len > __NEW_UTS_LEN)
                       return -EINVAL;
               down_write(&uts_sem);
               errno = -EFAULT;
               if (!copy_from_user(system_utsname.nodename, name, len)) {
                       system_utsname.nodename[len] = 0;
                       errno = 0;
               }
               up_write(&uts_sem);
               return errno;
       }

       asmlinkage long sys_gethostname(char *name, int len)
       {
               int i, errno;

               if (len < 0)
                       return -EINVAL;
               down_read(&uts_sem);
               i = 1 + strlen(system_utsname.nodename);
               if (i > len)
                       i = len;
               errno = 0;
               if (copy_to_user(name, system_utsname.nodename, i))
                       errno = -EFAULT;
               up_read(&uts_sem);
               return errno;
       }
       ______________________________________________________________________

  ̗̃|Cg͈ȉ̒ʂłB

  1. ֐́Acopy_from_user()/copy_to_user()ŁAf[^[UXy[X
     A̓[UXy[XփRs[ƂɃubN邱Ƃ
     BȂ킿Ał͂Ȃ^CṽXsbNƂ͂
     ȂB

  2. x[VbNł͂Ȃǂݏ̃Z}tHI΂Ă̂
     gethostname(2)vɂ񔭐邪A݂͌Ɏs
     Kv͂Ȃ߂łB

  Linux ̃Z}tHȂтɓǂݏZ}tH͔̎ɐIɂłĂ
  A܂ĂȂl\ȃViI݂Ă܂BႦ
  ΁A荞݉\ȓǂݏZ}tH̃RZvgȂǂłB̂悤ȃGL
  ]`bNȎނ̃v~eBuKvɂȂ󋵂́AEłȂ󋵂Ȃ
  ŁÂ悤ȃRZvg͖炩ɂ肦܂B

  2.15.  W[ǂݍ݂̃J[lT|[g

  }CNJ[lfUCɊÂIy[eBOVXe̒񋟂"A
  hoe[W"Ƃŋ߂̐`ɂւ炸ALinux ̓mVbNȃI
  y[eBOVXełBہA(Linus Torvalds ގǧtɂ
  )

       ... message passing as the fundamental operation of the OS is just an
       exercise in computer science masturbation. It may feel good, but you
       don't actually get anything DONE.

  ALinux  ƃmVbNfUCx[XƂĂAׂ
  ̃TuVXe͓[hœAAhXԂLĂ
  łBJ[l̒ʐM͒ʏ C ֐Ăяoōs܂B

  AƂ}CNJ[ls悤ɃJ[l̋@\ꂼ
  uvZXvւƕ邱Ƃ͖炩ɈlłAIf}hœI
  ɓǂݍ߂J[lW[ɕ邱Ƃ́A(Ⴆ΁A}V
  ̃ȂꍇA݂ɔrIȕ ISA ʃfoCXh
  CoJ[lCXg[ꍇ)ł́AlłB[_
  uW[̃T|[ggݍނǂ̔f́ARpCɍs
  ACONFIG_MODULES IvVɂĎw肳܂B request_module()
  @\ɂ郂W[̎gݍ݂̃T|[ǵAʂ̃RpCIvV
   (CONFIG_KMOD) ɂȂĂ܂Bȉ̋@\ Linux ̃[h\
  W[ƂĎĂ܂B

  1. LN^ȂтɃubNfoCXhCoBmisc foCXhCo
     ܂ށB

  2. ^[~iC֌WB

  3. /proc devfs ɂ鉼z(ʂ)t@C (Ⴆ
     /dev/cpu/microcodedev/misc/micrococe)B

  4. oCit@CtH[}bg (Ⴆ ELF, aoutȂ)B

  5. shC (Ⴆ, Linux, UnixWare7, SolarisȂ)B

  6. t@CVXeB

  7. System V IPCB

  ꕔɂ Linux ɂ郂W[ƂĎłĂȂ̂
  B(炭̓W[ɂčlĂȂ߂Ǝv
  j

  1. XPW[OASY

  2. VM|V[

  3. obt@LbVAy[WLbV₻̑̃LbV

  Linux ɂ̓[h\W[邢낢ȃVXeR[
  ܂B

  1. caddr_t create_module(cost char *name, size_t size): vmalloc()p
     sizeoCg蓖āAW[̍\̂̐擪Ɋt
     BVW[ module_list 擪ɂ郊XgւƃN
     BCAP_SYS_MODULẼvZX݂̂ÃVXeR[Ăяo
     ƂłÃvZXEPERMG[ԂB

  2. long init_module(const char *name, struct module *image): Ĕzu
     ꂽW[C[Wǂݍ݁AW[̏[`N
     BCAP_SYS_MODULEݒ肳ꂽvZX݂̂̃VXeR[
     ĂяoƂłAȊȌꍇEPERMG[ԂB

  3. long delete_module(const char *name): W[A[h悤
     ƂBname == NULLȂ΁ASĂ̎gpĂȂW[
     OƂB

  4. long query_module(const char *name, int which, void *buf, size_t
     bufsize, size_t *ret): W[(Ȃ͑SẴW[)
     ԂB

  [UgR}hC^[tF[X͎̒ʂłB

  o  insmod: ̃W[}B

  o  modprobe: W[̈ˑSẴW[ƂƂɑ}
     B

  o  rmmod: W[O܂B

  o  modinfo : W[ɂĂ̏\BႦ΁AҁAeA
     W[̎󂯎p[^ ȂǁB

  insmodmodprobegăW[蓮œǂݍނƂł͓̂R
  łA̋@\KvɂȂƂɁAJ[lIɃW[
  ǂދ@\܂B̋@\̃J[lC^[tF[X
  request_module(name)Ƃ֐ŁAW[փGLX|[gĂ
  BāAW[͑̃W[𓯗lɓǂݍނƂł̂
  B request_module(name)͓IɃJ[lXbh쐬AW
  exec_usermodehelper()J[lC^[tF[X(܂W[
  GLX|[gĂ܂)gāA[UԂ̃R}hmodprobe -s
  -k module_names܂B֐͐0Ԃ܂
  Arequest_module()̕Ԃl`FbN邱Ƃɒʏ͈Ӗ͂܂
  B̂AvO~Oł́A

       ______________________________________________________________________
       if (check_some_feature() == NULL)
           request_module(module);
       if (check_some_feature() == NULL)
           return -ENODEV;
       ______________________________________________________________________

  ̂悤ɂ̂ʗłB

  Ⴆ΂́Afs/block_dev.c:get_blkfops()ɂAW[ԍNł
  悤ȃubNfoCXI[v悤ƂƂɁAW[
  block-major-Nǂݍނ߂Ɏs܂B炩ɁAblock-major-N
  W[݂͑Ă܂(Linux J҂́AW[ɂ͂
  Ȃ̖OIԂ̂ł)BłA/etc/modules.conft@CɂA
  W[Ɋ蓖ĂĂ̂łBAĂ̗ǂmꂽ
  W[ԍ(Ƃ̃W[)ɂẮAmodprobe/insmodR}h
  ́A/etc/modules.confɖIalias ȂƂAۂ̃W[
  Ȃɂ𕪂Ă܂B

  W[̓ǂݍ̗ǂႪAmount(2)VXeR[̓ɂ܂B
  mount(2)VXeR[̓t@CVXe^Cv𕶎ƂĎ󂯎
  Afs/super.c:do_mount()fs/super.c:get_fs_type()ւn܂B

       ______________________________________________________________________
       static struct file_system_type *get_fs_type(const char *name)
       {
               struct file_system_type *fs;

               read_lock(&file_systems_lock);
               fs = *(find_filesystem(name));
               if (fs && !try_inc_mod_count(fs->owner))
                       fs = NULL;
               read_unlock(&file_systems_lock);
               if (!fs && (request_module(name) == 0)) {
                       read_lock(&file_systems_lock);
                       fs = *(find_filesystem(name));
                       if (fs && !try_inc_mod_count(fs->owner))
                               fs = NULL;
                       read_unlock(&file_systems_lock);
               }
               return fs;
       }
       ______________________________________________________________________

  ̊֐ł́Aӂ_܂B

  1. ŏɁA^ꂽÕt@CVXełɓo^Ă邤
     猩悤ƂB(o^Ăt@CVXẽXgXV
     Ȃ)ǂݍ݂̂߂Ɏ擾 file_system_lock ̕ی̂ƁA
     ͎sB

  2. t@CVXeAVt@X擾悤
     ƂBāAW[̃z[hJEg 1 ₻ƂB
     ͐ÓIɃNꂽt@CVXeł͏ 1 ԂBW[
     Ƃă[ht@CVXełAݍ폜ĂƂł
      1 ԂB try_inc_mod_count()  0 Ԃꍇ͎s
     ƍlB܂AW[͂邪폜ĂƂŁA
     XȂ̂ƓƂłB

  3. (request_module())́AubN鑀s
     ߁Afile_system_lock𗎂ƂBĂ̎ɂ̓XsbN
     łȂBۂ̂ƂA̓ʂȏꍇɂ́A
     request_module()mubNł邱Ƃۏ؂ĂāA
     W[ǂݍ݂ReLXgŃAg~bNɎsꂽƂ
     Afile_system_lock𗎂ƂȂ΂ȂȂB́AW[
     [`ł́Â݂߂ɓfile_systems_lockĂяo
     register_filesystem()ĂяoƂ邩łB

  4. [hAfile_systems_lockXsbN擾AV
     o^ꂽt@CVXeXg։悤ƂB͏
     lłBƂ̂́AIɂmodprobe R}h̃oOɂȂ蓾
     邩炾B request_module()sAVt@CVXeo
     ^Ă܂āAget_fs_type()ȂꍇɁAv
     W[̃[hɃRA_vĂ܂Ƃ邽
     ߂B

  5. t@CVXeÃt@X擾ł畜A
     BłȂ΁ANULL ԂB

  W[J[lɃ[hĂƂAJ[l EXPORT_SYMBOL()
  }NgĂ镔⌻݃[hĂ鑼̃W[Apu
  bNɃGLX|[gꂽV{QƂ邱Ƃł܂BB
  W[̃W[̃V{gƂ́Au[gdepmod
  -aR}h̎sɂsˑ֌W̍ČvZ̊Ԃ(ႦΐVJ[
  lCXg[Ȃ)ÃW[͕ۗ邱ƂɂȂ
  B

  ʏAgpJ[lC^[tF[X̃o[WƁAW[ꎮ
  o[W͈vȂ΂Ȃ܂B Linux ł́AʂȃJ[l
  C^[tF[X̃o[W@\ʂɂ͎ĂȂ߁AP
  uJ[lo[WvӖĂ܂BAuW[o[W
  vȂCONFIG_MODVERSIONS ƌĂ΂肳ꂽ@\Ă
  BɂāAVJ[lɈڍsƂɃW[̍ăRpC
  邱Ƃł܂BJ[l̃V{e[uÃANZX
  ƃW[̃ANZXʁXɈƂŁAĂ܂BV{
  e[ũpubN(܂GLX|[gꂽjvf́AC̏Cqɂ
  32rbg`FbNT܂BāA[hɃW[g
  V{邽߂ɁA[_̓`FbNT܂߂ăV{̕\L
  r܂BvȂ΃[hۂ悤ɂȂĂ܂B
  ́AJ[lƃW[AW[o[WLɂăRp
  CƂ̂݋N܂BAǂ炩IWĩV{g
  ĂꍇA[_͒PɃW[ɂăJ[lo[W̏Ĉ
  ̂ƁAJ[lɂGLX|[gĂ̂rāA
  ΃[hۂ܂B

  3.  zt@CVXe (VFS)

  3.1.  Inode LbVDcache Ƃ̑ݍp

  ̃t@CVXeT|[g邽߁A Linux  VFS (Virtual
  Filesystem Switch) ƂʂȃJ[lC^[tF[Xx
  ܂B SVR4 h OS Ɍ vnode/vfs C^[
  tF[XɗǂĂ܂ (ƂƂ́ABSD  Sun ɗR̎炫
  ܂)B

  Linux  inode LbV́A 977 sȂt@C fs/inode.c
  ɎĂ܂BMׂɁÃt@ĆA 5-7 N̊Ԃ
  ƂǕύX܂łBԍŌɍXVꂽ̂́A 1.3.42 
  Ȃ̂łB

  Linux  inode LbV̍\͈ȉ̒ʂłB

  1. e inode X[p[ubN|C^ 32bit  inode ԍ̒lɂ
     ănbVO[onbVe[u inode_hashtableB X[
     p[ubN̖ inode (inode->i_sb == NULL) ́A
     anon_hash_chainŎn܂_uNXgւƂȂB
     inode̗ƂāAfs/inode.c:get_empty_inode()ĂԂ
     ŁAnet/socket.c:sock_alloc()ɂč\PbgB

  2. i_count>0  i_nlink>0 ƂȂ inode ȂO[o^Cv
     in_use_list(inode_in_use)Binode ́Aget_empty_inode() 
     get_new_inode() ɂVɊ蓖ĂAinode_in_use Xgւ
     B

  3. i_count = 0ł悤 O[o^Cv̖gpXg
     (inode_unused)B

  4. i_count>0Ai_nlink>0i_state & I_DIRTY ł悤 inode ɂ
     X[p[ubN̉ꂽXg(sb->s_dirty)Binode dirtÿ
     ꂽA͂͂nbVɂȂĂsb->s_dirtyXg
     ǉBX[p[ubN inode  dirty XgǗ邱
     ƂŁAinode ̓΂₭sƂł悤ɂȂB

  5. ȈӖ inode LbV -- inode_cachepĂяo SLAB Lb
     VBinode IuWFNg蓖ĂꂽAꂽ肷Ƃ
     ́A SLAB LbV擾ꂽAԂꂽ肷B

  ꂼ̃^CvXǵAinode->i_listwAnbVe[u
  ́Ainode->i_hash猋ѕtĂ܂Be inode  ꂼnb
  Ve[uƂPނ݂̂̃^CvXg(in_use, unused, ܂ dirty)
  ܂B

  ׂ̂ẴXg͈̃XsbNinode_lockɂی삳Ă
  B

  inode LbVTuVXéAinode_init()֐
  Ainit/main.c:start_kernel()Ăяoꂽɏ܂B
  ֐́A__initƃ}[NĂA͂̌ÃR[h
  ܂ƂӖĂ܂B̊֐͈̈ -- VXe̕y[
  Wn܂B̂ƂAinode LbV͗p\ȃʂɈ
  Č߂Ă邱Ƃ킩܂B܂A\ȗʂ̃
  ΁A傫ȃnbVe[u쐬ƂƂłB

  inode LbVɊւ̗B̓vÍApĂȂinode
  łB́Ainodes_stat.nr_unusedɊi[At@C
  /proc/sys/fs/inode-nrproc/sys/fs/inode-stateʂă[UvO
  猩邱Ƃł܂B

  ̂߁AJ[lŎs gdb 烊XgoƂł
  B

       ______________________________________________________________________
       (gdb) printf "%d\n", (unsigned long)(&((struct inode *)0)->i_list)
       8
       (gdb) p inode_unused
       $34 = 0xdfa992a8
       (gdb) p (struct list_head)inode_unused
       $35 = {next = 0xdfa992a8, prev = 0xdfcdd5a8}
       (gdb) p ((struct list_head)inode_unused).prev
       $36 = (struct list_head *) 0xdfcdd5a8
       (gdb) p (((struct list_head)inode_unused).prev)->prev
       $37 = (struct list_head *) 0xdfb5a2e8
       (gdb) set $i = (struct inode *)0xdfb5a2e0
       (gdb) p $i->i_ino
       $38 = 0x3bec7
       (gdb) p $i->i_count
       $39 = {counter = 0x0}
       ______________________________________________________________________

  ŁAinclude/linux/list.h  list_entry()}N̒`ɂ
  struct inodẽAhX (0xdfb5a3e0) 𓾂邽߂ɁAAhX
  0xdfb5a2e8 8Ă邱Ƃɒӂ܂傤B

  inode LbVǂ̂悤ɓ邽߂ɁAext2 t@CVXe
  ̒ʏ̃t@CŁAI[vAN[YƂ inode ̈ꐶ
  Ă܂傤B

       ______________________________________________________________________
       fd = open("file", O_RDONLY);
       close(fd);
       ______________________________________________________________________

  open(2) VXeR[ fs/open.c:sys_open() ֐ɒ`ĂāA
  ̂ fs/open.c:file_open() ֐sĂ܂B̊֐2̕ɕ
  A

  1. open_namei():  dentryvfsmount\̂Ȃnameif[^\̂
     ߂B

  2. dentry_open(): dentryvfsmount^B̊֐́AVstruct
     file蓖āA݂ɃNB܂Ainode (dentry->d_inode
      inode ^) open_namei() œǂݍ܂鎞 inode->i_fop 
     ZbgĂt@CVXeɓL f_op->open() \bh
     яoB

  open_namei() ֐́At@CVXeinode_operations->lookup() 
  \bhN real_lookup()ɌĂяo path_walk() ɂāA
  dentry LbVƑݍpN܂B̃\bh̖́AefB
  NgŖÖvGgTƂŁA inode 擾邽
   iget(sb, ino) ĂяoĂ܂B̊֐ inode LbVփAN
  ZX܂B inode ǂݍ܂ꂽA d_add(dentry, inode) ɂ
  dentry ̃CX^X쐬܂BŒӂ̂́AL̊ԂŁA
  IfBXN inode ԍƂRZvgUNIX X^C̃t@CV
  Xê߂ɁÃGfBA݂ CPU tH[}bgɃ}bv
  ̂bNAbv\bh̎dƂƂłBƂ΁At@CVX
  eɓL raw fBNgGg inode ԍgGfBA
  32rbgtH[}bgł΁A

       ______________________________________________________________________
       unsigned long ino = le32_to_cpu(de->inode);
       inode = iget(sb, ino);
       d_add(dentry, inode);
       ______________________________________________________________________

  ƂR[hs܂B

  ̂悤ɁAt@CJƂɂ́Âiget4(sb, ino, NULL, NULL)
  ł iget(sb, ino) ܂B́A

  1. inode_lock̕ی̂ƁAnbVe[u̒AX[pubN
     inode ԍv inode 悤ƂBAinode 
     ΁A̎QƃJE^ (i_count) 𑝕BȂO̒l 0
     ł΁Ainode  dirty ł͂Ȃ̂ŁAǂ̃^CṽX
     g(iode->i_list)ł폜B́A on (͂
     inode_unusedXgłȂ΂ȂȂ)łAinode_in_use^Cv
     Xgɑ}BŌɁAinodes_stat.nr_unused B

  2. inode݃bNĂAbN܂ő҂B
     Aiget4()̓bNĂȂ inode ԂƂۏ؂B

  3.  inode nbVe[uɌȂ΁A inode ɏ
     ďoƂƂɂȂBāAget_new_inode()ĂяoAnb
     Ve[ȗ}ׂʒu|C^œnB

  4. get_new_inode() ͐V inode inode_cachep SLAB LbV犄
     蓖ĂBȂ( GFP_KERNEL蓖Ă)ubNł邽
     ߁AnbVe[u inode_lock spinlock hbvȂƂ
     ȂBspinlock hbvĂ܂߁AōĂуnbVe[u
      inode Ă݂ȂĂ͂ȂȂBēxꂪ΁Anb
     Ve[uŌ̂𕜋AA(__iget ɂĎQƐ𑝂₵
     )AV蓖Ăꂽ inode jBnbVe[u
     ܂Ȃ΁A蓖ĂV inode Ag
     ̂ƂȂBāA͗vꂽlɏB
     āAt@CVXeɓL sb->s_op->read_inode() \bh́Ac
      inode g߂ɋNBƂƂŁAinode LbV
     obÑR[hAt@CVXeR[h֌ɍsȂ΂Ȃ
     BŁAt@CVXeɓL lookup() \bh iget()N
     ߂ɁA inode LbṼR[hǂł邱Ƃvo
     قB s_op->read_inode() \bhfBXNinodeǂݍ
     ԁAinode ̓bNB(i_state = I_LOCK()) read_inode() \b
     hAɃbNBāAinode bN҂Ă
     SĂNB

     āÃt@CfBXNv^closeƂɁAȂɂN邩
     ݂Ă܂Bclose(2) VXeR[́Ado_close(fd, 1) Ăяo
     fs/open.c:sys_close() ֐ƂĎĂ܂Bdo_close(fd, 1)
     ́AvZX̃t@CfBXNv^e[űLqq𔍂(NULL
     Œu)AقƂǂ̍Ƃs filp_close() ֐Ăяo
     B fput()ł͂낢ƂN܂Bꂪt@C̍Ō̃
     t@XłȂ΁A__fput()Ăт fs/file_table.c:_fput()
     ĂяoAdcache ƑݍpN܂B( inode cache 
     p܂ -- dcache  inode LbṼ}X^[ł!)
     fs/dcache.c:dput() ́A X iput(inode)oRinode Lb
     Vֈ߂Ădentry_iput()s܂B
     āAfs/inode.c:iput(inode)͎̂悤ɗ邱Ƃł܂B

  1. nꂽp[^ NULL Ȃ΁A{ɉ߂B

  2. AfsL sb->s_op->put_inode() \bh΁A(ubN
     邽)XsbN擾邱ƂȂɋNB

  3. inode_lockXsbN擾 i_count PB
      inode ւ̍Ō̃t@XŁȂꁖ΁APɃt@
     XȂǂmFB́Ai_count 蓖Ăꂽ
     32bit ȓɔ[߂邽߂łBAt@Xꍇ͌x
     \ĕԂBŁAinode_lock XsbN擾ĂƂ
      printk() ĂяoA͑vłBƂ̂́Aprintk()
     ̓ubN邱Ƃ͂ȂAĂȂReLXg(
     ݃nhł)łĂяoƂł邽߂B

  4. Ō̃ANeBuȃt@Xłꍇɂ́AKvȏ
     B

  Ō inode t@Xł iput() śA╡GȂ̂
  B̂߁AXgł̍ŌɕĂ܂B

  1.  i_nlink == 0 (: t@CI[vĂƂ unlink 
     )ꍇ́A inode ̓nbVe[utype list 폜B
     A inode ̃y[WLbVɂȂɂf[^y[WێĂ
     Atruncate_all_inode_pages(&inode->i_data) ɂ폜B
     āAt@CVXeL s_op->delete_inode()\bhĂяo
     B͒ʏ́AfBXN inode 폜B
     As_op->delete_inode()\bht@CVXeɂo^
     Ȃ(: ramfs)ꍇɂ́Aclear_inode(inode)ĂяoA͂
     o^Ăs_op->clear_inode()ĂяoB܂Ainode 
     ubNfoCXɊ֘AĂ΁AfoCX̃t@XJEg
     bdput(inode->i_bdev)ŗƂB

  2.  i_nlink != 0 ȂAnbVoPbg̑ inode 邩
     `FbNBāAȂ inode  dirty ł͂Ȃ߁A
     type list 폜łB āAinode_unusedXg֒ǉ
     Ainodes_stat.nr_unused𑝕BAꂪ inode ł
     (NetApp .snapshot)ȂA^CvXg폜ASɃNA/j
     B

  3.2.  t@CVXeo^/o^

  LinuxJ[ĺAVt@CVXeŏ̓w͂ŏƂł
  @\񋟂Ă܂B̗jIȗRƂ͎̂悤Ȃ̂łB

  1. lXLinuxȊÕIy[eBOVXegĂ鐢EŁAÂ\
     tgEGAւ̓ی삷邽߂ɁALinux͑ϑ̈قȂt@C
     t@CVXẽT|[gɂ葊݉^p񋟂Ȃ΂Ȃ
     B̂߁Ãt@CVXe͂ꎩg݂̑͂ق
     dvł͂ȂALinuxȊÕIy[eBOVXeƂ̌
     Ƃ邽߂̖ړIő݂B

  2. t@CVXeLqC^[tF[X͂ƂĂVvȂ̂
     Ȃ΂ȂȂBvvG^ȃt@CVXeA
     Ǎ݂̂݉\ȃt@CVXeƂɂăo[XGWj
     AOł悤ɂ邽߂ɁAt@CVXeLqC^[
     tF[X͂ƂĂVvȂ̂łȂ΂ȂȂB
     āALinuxVFS͓Ǎݐpt@CVXe̎ɗeՂɂȂ
     ĂBt@CVXẽT|[gd̂95%́Ã݂t
     T|[gǉĊ邱Ƃɔ₳̂łB̓Iȗ
     ƂẮALinuxpɓǍݐpBFSt@CVXêɖ
     POԂłł̂ɑ΂āASȏ݃T|[gǉĊ
     ̂ɐTԂvƂ(A݂ł`҂
     A"compactificationT|[gȂ"ĂȂ
     咣̂)B

  3. VFS C^[tF[X̓GLX|[gĂAĂׂ
     Linuxt@CVXe̓W[ƂĎłB

  ŁALinuxŃt@CVXe̎ɕKvȃXebvlĂ݂܂
  Bt@CVXeR[h́AIɃ[h郂W[
  AÓIɃJ[lɃN悤ɂ\邱Ƃł܂B
  āA Linux̌ōs@͔ɖłBKvȂƂ́Astruct
  file_system_type\̂ɏ𖄂߂āAVFSregister_filesystem()
  ֐ɂēo^邱ƂȂ̂łBfs/bfs/inode.c̗ႾƁAȉ̂
  ɂȂ܂B

  ______________________________________________________________________
  #include <linux/module.h>
  #include <linux/init.h>

  static struct super_block *bfs_read_super(struct super_block *, void *, int);

  static DECLARE_FSTYPE_DEV(bfs_fs_type, "bfs", bfs_read_super);

  static int __init init_bfs_fs(void)
  {
          return register_filesystem(&bfs_fs_type);
  }

  static void __exit exit_bfs_fs(void)
  {
          unregister_filesystem(&bfs_fs_type);
  }

  module_init(init_bfs_fs)
  module_exit(exit_bfs_fs)
  ______________________________________________________________________

  module_init()/module_exit()}ŃABFSW[ƂăRpC
  ꂽƂɁA֐init_bfs_fs()exit_bfs_fs()ꂼAinit_module()
  cleanup_module()ɂȂ悤ɂ܂B

  struct file_system_typéAinclude/linux/fs.hŒ`܂B

       ______________________________________________________________________
       struct file_system_type {
               const char *name;
               int fs_flags;
               struct super_block *(*read_super) (struct super_block *, void *, int);
               struct module *owner;
               struct vfsmount *kern_mnt; /* For kernel mount, if it's FS_SINGLE fs */
               struct file_system_type * next;
       };
       ______________________________________________________________________

  ꂼ̃óÂ悤ɐ܂B

  o  name: lǂ߂閼OŁAfilesystemsproct@C֌܂B
     āAt@CVXe𖼑O猩Ƃ̃L[ƂĎg܂B
     ƓÓAmount(2)֎w肷t@CVXẽ^CvƂ
     gAt@CVXeƂɈӂłȂ΂Ȃ܂B

  o  fs_flags: PȂ(ORꂽ)̃tO: FS_REQUIRES_DEV́Au
     bNfoCXɂ}Eg\ȃt@CVXeƂ
     BFS_SINGLÉABP̃X[p[ubNt@CVXe
     AFS_NOMOUNT̓[UXy[X}EgłȂA܂mount(2)
     VXeR[Ń}EgłȂt@CVXeB́A
     Iɂkern_mount()C^[tF[Xg΃}Egł (
     pipefs)B

  o  read_super: }Eg쒆ɃX[pubNǍފ֐ւ̃|C
     ^B̊֐͕K{łB̃|C^nȂȂA}E
     g([UԂɂJ[lɂ)FS_SINGLȄꍇ
     ɎsA fs_type->kern_mnt->mnt_sb(fs_type->kern_mnt = NULL)
     ̂悤ɎQƂ悤ƂāAget_sb_sinle()Oops G[B

  o  owner: ̃t@CVXeĂ郂W[ւ̃|C^B
     t@CVXeJ[lɐÓIɃNĂ΁A̒l
     NULLƂȂB蓮Őݒ肷Kv͂ȂA}N THIS_MODULE 
     ĎœK؂ɐݒ肳B

  o  kern_mnt: FS_SINGLEt@CVXêݗpBkern_mount()
     肷B(TODO: kern_mount()FS_SINGLEݒ肳ĂȂt@CV
     Xẽ}Egۂׂł)B

  o  next: file_systemsɂЕXg̐擪ւ̃N (fs/super.c
     Q)BXǵAfile_systems_lockǂݏXsbNɂی삳
     ĂAregister/unregister_filesystem()֐́AXgGg
     OAꂽ肷邱ƂŕύXsB

  read_super()֐̎d́AX[p[ubÑtB[h𖄂߂邱Ƃ
  B inodȅꏊ蓖āA}Egꂽt@CVXẽCX^
  XɊ֘AÂꂽfsŗL̏܂B

  1. obt@LbVbread()֐gāAX[p[ubNsb->s_dev
     ŎwfoCXǂݎB

  2. X[pubN}WbNio[ȂĂ邩mFAS
     Iɐł邩uvB

  3. sb->s_opstruct super_block_operations\̂w悤ɏ
     B̍\̂́AuinodeǂݎvƂAuinode폜vȂ
     ̂悤ȑĂt@CVXeL̊֐ȂB

  4. d_alloc_root()pă[ginodeƃ[gdentry蓖ĂB

  5. t@CVXeǂݎpŃ}EgĂȂ
     ΁Asb->s_dirt1ɐݒ肵AX[p[ubNȂobt@dirty
     ƃ}[N(TODO: ȂꂪKv?BFSł́AMINIXĂ̂
     Ă邪...)

  3.3.  t@CfXNv^Ǘ

  LinuxɂẮA[Ut@CfXNv^ƃJ[linode\̂̊
  ɊԐړIȃx݂Ă܂BvZXopen(2)VXeR[Ă
  oƂAJ[ĺÃt@CI/OŎgp鏬̐
  Ԃ܂B̐́Astruct fileւ̃|C^̔z̃CfbNX
  ɂȂĂ܂Bet@C\̂́Afile->f_dentryʂāAdentryw
  Ă܂BĊedentrydentry->d_inodeʂinodewĂ
  B

  e^XŃAinclude/linux/sched.hŒ`Ăstruct files_struct
  wĂtsk->filestB[hĂ܂B

  ______________________________________________________________________
  /*
   * Open file table structure
   */
  struct files_struct {
          atomic_t count;
          rwlock_t file_lock;
          int max_fds;
          int max_fdset;
          int next_fd;
          struct file ** fd;      /* current fd array */
          fd_set *close_on_exec;
          fd_set *open_fds;
          fd_set close_on_exec_init;
          fd_set open_fds_init;
          struct file * fd_array[NR_OPEN_DEFAULT];
  };
  ______________________________________________________________________

  file->count͎QƃJE^łA(ʏAfget()Ăяo
  )get_file()őAfput()put_filp()Ō܂Bfput()
  put_filp()̈Ⴂ́Afput()ʂ̃t@CɒʏKvȁAt@Cb
  N̊JdentrẙJȂǂ̒ǉ̏ŝɑ΂Aput_filp()͒P
  t@Ce[u\̂𑀍삷ɉ߂ȂƂɂ܂B܂AJ
  E^̌file_lockXsbN̕ی̂ƁAanon_listt@C
  폜Afree_list֒ǉƂƂłB

  q̃XbhN[tOCLONE_FILESݒ肵clone()VX
  eR[Ăōꂽ̂ł΁Atsk->files͐eƎq̊ԂŋL
  邱Ƃł܂B́A(do_fork()ɂČĂ΂
  )kernel/fork.c:copy_files()ɂČ邱ƂłÁA
  CLONE_FILESA`Iȏ]̌ÓTIUNIXfork(2)ɂʏ̃t@C
  fXNv^e[ũRs[̂ɐݒ肳Ă΁AP
  file->count𑝕邾łB

  t@CJƂAɊ蓖Ăt@C\
  ́Acurrent->files->fd[fd]Xbg֑gݍ܂܂Bărbg}b
  vcurrent->files->open_fdsfdrbgZbg܂B̂Ƃ͑S
  āAcurrent->files->file_lockǂݏXsbN̏ݕی̂
  ōs܂BAfXNv^close΁A
  current->files->open_fdsfdrbg̓NAÃvZXt@C
  ɃI[vgpƂƂɁAŏ̖gp̃fXNv^
  ߂̃qgƂāAcurrent->files->next_fdfdƓɂȂ悤ݒ肳
  ܂B

  3.4.  t@C\̊Ǘ

  t@C\̂ include/linux/fs.hŒ`Ă܂B

  ______________________________________________________________________
  struct fown_struct {
          int pid;                /* pid or -pgrp where SIGIO should be sent */
          uid_t uid, euid;        /* uid/euid of process setting the owner */
          int signum;             /* posix.1b rt signal to be delivered on IO */
  };

  struct file {
          struct list_head        f_list;
          struct dentry           *f_dentry;
          struct vfsmount         *f_vfsmnt;
          struct file_operations  *f_op;
          atomic_t                f_count;
          unsigned int            f_flags;
          mode_t                  f_mode;
          loff_t                  f_pos;
          unsigned long           f_reada, f_ramax, f_raend, f_ralen, f_rawin;
          struct fown_struct      f_owner;
          unsigned int            f_uid, f_gid;
          int                     f_error;

          unsigned long           f_version;

          /* needed for tty driver, and maybe others */
          void                    *private_data;
  };
  ______________________________________________________________________

  ł struct file ̃oĂ܂傤B

  1. f_list: ̃õ͎Xĝ(ĂЂƂ)̃t@C
     \̂NBa) ̃t@CVXȇSẴI[vĂ
     t@Csb->s_filesXgA֘AinodełȂ
     ΁A(filp_open()΂)dentry_open()́ÃXgɃt@C
     NBb) fs/file_table.c:free_list, gp̃t@C\
     ȂBc) fs/file_table.c:anon_list, get_empty_filp()ɂĐV
     t@C\̂ꂽƂɂ̃XgɂBׂẴ
     Xgfiles_lockXsbNɂĕی삳B

  2. f_dentry: ̃t@CɊ֘AÂdentryBdentry
     ́Aopen_namei()nameidataTƂ(邢́AĂяo
     path_walk()sꂽƂ)ɍBA
     file->f_dentryodentry_open()ɂāÂ悤ɂČ
     dentryɃZbgB

  3. f_vfsmnt: ̃t@Cvfsmountt@CVXe\̂wB
     ́Adentry_open()ɂĐݒ肳邪Aopen_namei()(Ȃ́A
     Ăяo path_init()) ɂ nameidata ̈ꕔƂČ邱Ƃł
     B

  4. f_op: ̃t@CŋN邳܂܂ȃ\bh
     file_operationswB́AnameidatǎɃt@CVXe
     Ls_op->read_inode()\bhɂčꂽAinode->i_fop
     Rs[B̃ZNV̌̕ŁAfile_operations\bh
     ڍׂɌĂƂɂ悤B

  5. f_count: get_file/put_filp/fputɂ葀삳郊t@XJE
     ^B

  6. f_flags: dentry_open()ɂ(filp_open()኱̕ύX)R
     s[open(2)VXeR[O_XXXt
     OBO_CREATAO_EXCLAO_NOCTTYAO_TRUNCNA͂̃t
     O𒷂ԕۑĂӖ͂ȂBȂȂAF_SETFL  F_GETFL
     fcntl(2) VXeR[ŕύX邱ƂA₢킹邱Ƃ
     łB

  7. f_mode: [UԂ̃tOƃ[h̑gݍ킹Bdentry_open()ɂ
     Đݒ肳Bϊ̃|CǵAǂݏ̃ANZXʂ̃rbg֊i
     [邱ƂŁA(f_mode & FMODE_WRITE)(f_mode & FMODE_READ)̂悤
     `FbNeՂɂ邱ƂłB

  8. f_pos: ̃t@C̓ǂݏɂ錻݂̃t@CʒuBi386
     ́Along long^A܂64rbglɂȂB

  9. f_reada, f_ramax, f_raend, f_ralen, frawin: readaheadT|[g
     B -- GĐlԂɂ͋c_łȂ ;)

  10.
     f_owner: 񓯊I/OʒmSIGIO@\ʂĎ󂯎t@CI/ȌL
     ҁB(fs/fcntl.c:kill_fasync()Q)

  11.
     f_uid, f_gid: t@C\̂get_empty_filp()ɂčꂽƂ
     Ƀt@CJvZX̃[UIDƃO[vIDɐݒ肳Bt@
     C\PbĝƂ́Aipv4lbgtB^gB

  12.
     f_error: ݃G[Ԃ߂NFSNCAgpB
     fs/nfs/file.cŐݒ肳Amm/filemap.c:generic_file_write()
     `FbNB

  13.
     f_version: LbV߂̃o[WǗJjYB(O
     [oϐeventg)f_posςƂɂB

  14.
     private_data: t@CVXegƂł(Ⴆ΁Acoda ͂
      ؖi[) J̃t@C̃f[^BȂ́AfoC
     XhCogB(devfsɂ)foCXhCóÃo
     Afile->f_dentry->d_inode->i_rdevɕAÓTIȃ}Ci[
     ԍ̂ɁÃCX^XԂʂ̂ɎgB

  āAt@CɂċNł郁\bhłĂ file_operations
  \̂Ă݂܂傤Binode->i_fopRs[邱ƂA
  s_op->read_inode()\bhɂĐݒ肳邱ƂȂǂoĂ
  傤B́Ainclude/linux/fs.hŒ`Ă܂B

  ______________________________________________________________________
  struct file_operations {
          struct module *owner;
          loff_t (*llseek) (struct file *, loff_t, int);
          ssize_t (*read) (struct file *, char *, size_t, loff_t *);
          ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
          int (*readdir) (struct file *, void *, filldir_t);
          unsigned int (*poll) (struct file *, struct poll_table_struct *);
          int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
          int (*mmap) (struct file *, struct vm_area_struct *);
          int (*open) (struct inode *, struct file *);
          int (*flush) (struct file *);
          int (*release) (struct inode *, struct file *);
          int (*fsync) (struct file *, struct dentry *, int datasync);
          int (*fasync) (int, struct file *, int);
          int (*lock) (struct file *, int, struct file_lock *);
          ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
          ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  };
  ______________________________________________________________________

  1. owner: __ƂȂĂTuVXeLĂ郂W[wB
     hCô݂THIS_MODULEɐݒ肷KvAW[̃J
     EǵAhCoopen/releaseɐ䂷Kv̂ɑ΂
     āAmount/umount̂Ƃɐ䂳邽߁At@CVXe͍K^Ȃ
     ƂɖłB

  2. llseek: lseek(2)VXeR[ĂBʏA͏ȗ
     Afs/read_wirte.c:default_llseek()gB͐@
     B(TODO: default_llseekg߂Ɍ݂NULLݒ肵Ȃ
     ΂ȂȂȂĂB̂Ƃ́Allseek()if()ۑĂ)B

  3. read: read(2)VXeR[̎Bł́At@CVXe
     ́Amm/flemap.c:generic_file_read()ʏ̃t@C
     ɁAfs/read_write.c:generic_read_dir()(P-EISDIRԂ)fB
     NgɎgpłB

  4. write: write(2)VXeR[̎Bł́At@CVXe
     ́Amm/filemap.c:generic_file_write()ʏ̃t@CɎgpłA
     fBNg͖łB

  5. readdir: t@CVXegBʏ̃t@C͖AfBN
     gɂreaddir(2)  getdents(2) VXeR[B

  6. poll: poll(2)  select(2) VXeR[B

  7. ioctl: hCot@CVXeL ioctl ĂB
     ̃t@Cɑ΂ FIBMAP FIGETBSZA FIONREAD ̂悤ioctl ́A
     xŎĂf_op->ioctl() \bhǂނƂȂB

  8. mmap: mmap(2) VXeR[ĂBt@CVXe
     generic_file_mmapʂ̃t@Cɑ΂ĂŎgƂłAfB
     Ngɑ΂Ă͖B

  9. open: open(2) Ƃdentry_open() ĂԁBt@CVXe͖
     ɎgȂBႦ΁Acoda ̓I[vƂɃt@C[J
     LbV悤ƂB

  10.
     flush: t@C̊eclose(2)ƂɌĂ΂BKŌɌĂ΂K
     v͂ȂB(ȉrelease()\bhQ) gt@CVXe
     Ƃ̂́ABNFS̃NCAgŁASĂdirtyy[WoB
     ŁAclose(2)VXeR[A[UԂɑԂG[
     ԂƂB

  11.
     release: t@C̍Ōclose(2)ŌĂ΂B܂Afile->f_count
     0łƂBԂƒ`Ăɂւ炸AVFSł͕
     l͖B(fs/file_table.c:__fput()Q)

  12.
     fsync: fsync(2)/fdatasync(2)VXeR[ɒڑΉBŌ̈
     fsyncɂȂ邩fdatasyncɂȂ邩w肷BVFS ͂̍ۂقƂ
     dȂAt@CfBXNv^ file \̂ɑΉ
     邱 (file = fget(fd))A inode->i_sem Z}tH𑀍삷邱
     Ƃ͍sBExt2 t@CVXe͍Ō̈𖳎̂ŁAfsync(2)
      fdatasync(2) ̃VXeR[͑SB

  13.
     fasync: ̃\bh́Afile->f_flags & FASYNC ^łƂɎg
     B

  14.
     lock : t@CVXeɌŗLPOSIXfcntl(2)̃t@C̈惍bN
     @\Bł̗B̃oÓAfs ˑ(posix_lock_file())Ȃ̂
     ΂OɌĂ΂ꂽƂAʏPOSIXbNR[hs
      fs ˑxł́AbNłȂȂƂƂłB

  15.
     readv: readv(2)VXeR[̎B

  16.
     writev: writev(2)VXeR[̎B

  3.5.  X[p[ubNƃ}Eg|CgǗ

  Linux ɂẮA}Egꂽt@CVXeɂĂ̏2
  ꂽ\ super_blockvfsmount ŕێĂ܂B Linux
  ͓t@CVXe(ubNfoCX)𕡐̃}Eg|Cgփ}E
  gA܂蓯super_block vfsmount\̂֊֘AÂ
  ƂӖłAꂪĂ邱ƂA2ɕĊǗ闝
  RɂȂĂ܂B

  include/linux/fs.h Œ` struct super_block ŏɂ݂Ă
  B

  ______________________________________________________________________
  struct super_block {
          struct list_head        s_list;         /* Keep this first */
          kdev_t                  s_dev;
          unsigned long           s_blocksize;
          unsigned char           s_blocksize_bits;
          unsigned char           s_lock;
          unsigned char           s_dirt;
          struct file_system_type *s_type;
          struct super_operations *s_op;
          struct dquot_operations *dq_op;
          unsigned long           s_flags;
          unsigned long           s_magic;
          struct dentry           *s_root;
          wait_queue_head_t       s_wait;

          struct list_head        s_dirty;        /* dirty inodes */
          struct list_head        s_files;

          struct block_device     *s_bdev;
          struct list_head        s_mounts;       /* vfsmount(s) of this one */
          struct quota_mount_options s_dquot;     /* Diskquota specific options */

         union {
                  struct minix_sb_info    minix_sb;
                  struct ext2_sb_info     ext2_sb;
                  ..... all filesystems that need sb-private info ...
                  void                    *generic_sbp;
          } u;
         /*
           * The next field is for VFS *only*. No filesystems have any business
           * even looking at it. You had been warned.
           */
          struct semaphore s_vfs_rename_sem;      /* Kludge */

          /* The next field is used by knfsd when converting a (inode number based)
           * file handle into a dentry. As it builds a path in the dcache tree from
           * the bottom up, there may for a time be a subpath of dentrys which is not
           * connected to the main tree.  This semaphore ensure that there is only ever
           * one such free path per filesystem.  Note that unconnected files (or other
           * non-directories) are allowed, but not unconnected diretories.
           */
          struct semaphore s_nfsd_free_path_sem;
  };
  ______________________________________________________________________

  super_block \̂ɂ͗lXȃo܂B

  1. s_list: SẴANeBuȃX[p[ubÑ_uNXgB
     ŁAuSẴ}Egꂽt@CVXevƌȂ̂́ALinux
     ł́A̃X[pubNɊ֘AÂꂽ}Egꂽt@CV
     Xẽ̕CX^XĂ邽߂łB

  2. s_dev: }EĝɃubNKvƂt@CVXeA
      FS_REQUIRES_DEV ȃt@CVXeɂƂẮÃo͂̃u
     bNfoCX i_dev łB̑ (t@CVXeƌĂ
     ) t@CVXeɑ΂ẮA MKDEV(UNNAMED_MAJOR, i) 
     \鐮łB i ́Aunnamed_dev_in_use rbgz̒
     ōŏ OFF rbgwA1  255 ͈̔͂̒lł
     Bfs/super.c:get_unnamed_dev()/put_unnamed_dev() QƂ̂ƁB
     t@CVXe s_dev o𗘗pׂłȂƂƂ́A
     ܂ŉxĂĂB
  3. s_blocksize, s_blocksize_bits: ubNTCYlog2(ubNTC
     Y)B

  4. s_lock: X[p[ubNAlock_super()/unlock_super() ɂČ
     ݃bNĂ邩ǂB

  5. s_dirt: X[p[ubNύXꂽƂɐݒ肳AfBXN֏
     ߂ꂽƂ͂NAB

  6. s_type: ֘At@CVXe struct file_system_type w
     Bfs Lread_super()Ƃ VFS
     fs/super.c:read_super() ݒ肵AsƂ NULL ɃZbg
     ߁At@CVXe read_super() \bh͐ݒ肷Kv
     B

  7. s_op: fs Lread/write inodeȂǂ̃\bhȂ
     super_operations \̂ւ̃|C^Bs_op 𐳂̂́A
     t@CVXe read_super() \bh̎dłB

  8. dq_op: fBXNNI^B

  9. s_flags: X[p[ubNtOB

  10.
     s_magic: t@CVXẽ}WbNԍBminixt@CVXe
     ́Aꎩg̕o[Wʂ邽߂ɎgB

  11.
     s_root: t@CVXẽ[gdentryB[g inode fBXN
     ǂ݁Ad_alloc_root()Ădentry蓖ĂĎ̉邽߂
     n̂́Aread_super() ̎dłB

  12.
     s_wait: X[p[ubNbN̂҂vZX̑҂
     L[B

  13.
     s_dirty: SĂdirty  inode ̃XgB inode 
     (inode->i_state & I_DIRTY)΁AX[p[ubNL
     inode->i_listoRŃNꂽ dirty XgɂB

  14.
     s_files: ̃X[p[ubNŃI[vĂt@CSẴX
     gBt@CVXe read-only ōă}Egł邩𔻒fƂ
     ɗLpBsb->s_files Xg݂āAt@C݃I[v
     Ă(file->f_mode & FMODE_WRITE)AunlinkۗĂ
     (inode->i_nlink == 0)t@C΁Aă}Egۂ
     fs/file_table.c:fs_may_remount_ro()QƂ邱ƁB

  15.
     s_bdev: FS_REQUIRES_DEV ̂߂ɁA t@CVXe}Eg
     ĂfoCX\ block_device \̂wĂB

  16.
     s_mounts: SĂ vfsmount \̂̃XgB}Egꂽ̃X[
     p[ubN̊eCX^X???

  17.
     s_dquot: fBXNNI^pB

  X[p[ubN̑́Ainclude/linux/fs.h Œ`Ă
  super_operations \̂ɋLqĂB

  ______________________________________________________________________
  struct super_operations {
          void (*read_inode) (struct inode *);
          void (*write_inode) (struct inode *, int);
          void (*put_inode) (struct inode *);
          void (*delete_inode) (struct inode *);
          void (*put_super) (struct super_block *);
          void (*write_super) (struct super_block *);
          int (*statfs) (struct super_block *, struct statfs *);
          int (*remount_fs) (struct super_block *, int *, char *);
          void (*clear_inode) (struct inode *);
          void (*umount_begin) (struct super_block *);
  };
  ______________________________________________________________________

  1. read_inode: inodet@CVXeǂݍށBiget4()(
     āAiget())ʂāAfs/inode.c:get_new_inode() ̂݌Ă΂B
     t@CVXeiget()gȂ΁Aread_inode()͎
     ȂƂȂBłȂ΁Aget_new_inode()̓pjbNɂȂB
     inodeǂ܂ĂԂ̓bN(inode->i_state = I_LOCK)B֐
     畜AƂASĂinode->i_wait̑҂͋NBt@CV
     Xeread_inode()\bh̎d́Aǂݍ܂ inode Ȃ
     fBXNubN蓖āAobt@[LbV bread()֐g
     ēǂݍ݁Cinode \̗̂lXȃtB[hDႦ
     inode->i_op inode->i_fop ł́AVFSxAinode ֘A
     t@CłȂ̑삪s邩mĂ read_inode()
     t@CVXéAramfspipefsłBƂ΁AramfśAKv
     ɂȂƂɑSĂinode ̑삪ĂԁAginode
     ramfs_get_inode()ĂB

  2. write_inode: inode fBXNɏ߂Bread_inode()ƎāAfBX
     NɓlȃubN蓖āAmark_buffer_dirty(bh)ĂԂƂŁA
     obt@LbVƍpB̃\bh́AinodeAꂼ
     t@CVXeŜ̓̈ꕔȂœKv
     Adirty  inode (mark_inode_dirty()ɂ dirty ƈ
     Ă)ɑ΂ČĂ΂B

  3. put_inode: t@XJE^ƂɂĂ΂
     B

  4. delete_inode: inode->i_countinode->i_nlink0ɂȂƂ͏ɌĂ
     Bt@CVXéAIfBXNinodẽRs[폜AVFS
     clear_inode()ĂяoāAuSɍ₷vB

     -->

  5. put_super: umount(2)VXeR[̍ŏIiKŌĂ΂At@CVX
     eɑ΂āÃCX^Xɂăt@CVXeێĂ
     邢Ȃ̏Ȃ΂ȂȂƂʒmBT^I
     ɂ͂́AX[p[ubNubNbrelse()At[u
     bNinodeȂǂ̂߂Ɋ蓖Ăꂽrbg}bvSkfree()
     B

  6. write_super: X[p[ubNfBXNɏ߂KvƂɌ
     ΂B́AX[pubN(ʏsb-privatëɂ)
     mark_buffer_dirty(bh)ubNȂ΂ȂȂB
     ͂܂Asb->s_dirttONAB

  7. statfs: fstatfs(2)/statfs(2)VXeR[̎BƂēn
     struct statsւ̃|C^́A[U|C^ł͂ȂJ[l|C
     ^ł邽߁A[UԂւI/OsKvł邱Ƃɒӂ邱ƁB
     ĂȂ΁Astatfs(2)ENOSYSŎsB

  8. remount_fs: t@CVXeă}EgƂɂ͕KĂ΂B

  9. clear_inode: VFSxclear_inode()Ă΂BvCx[gf[^
     inode\̂(generic_ipooR)蓖Ăt@CVXe
     ́AŉȂ΂ȂȂB

  10.
     umount_begin: Ȃɂt@CVXerW[ɂȂƂm߂
     ̂ɑS͂sƂł悤ɁA炩߃t@CVXe֒
     m邽߁AumountԂɌĂ΂B݁ANFSł̂ݎgB
     ́AʓIVFSx̋umountT|[gƂ̊֌W͂ȂB

  ł́Aon-disk (FS_REQUIRES_DEV)t@CVXe}EgƂ
  ɋN邱ƂĂ܂傤B mount(2)VXeR[̎
  ́Afs/super.c:sys_mount() ɂA͎ۂ̏s do_mount()
  ֐ɃIvVƃt@CVXe^CvfoCXRs[PȂ
  bp[ɂȂĂ܂B

  1. t@CVXẽhCo͕KvɂȂƂɃ[hAW[
     ̎QƃJEgBŁA}Eg̍ŒɃt@CVX
     ẽW[ɂĂ̎QƃJEgɂẮA2邱
     ɒӂKvłBdo_mount()get_fs_type()ĂԂƂ1
     Aread_super()Ȃ΁Aget_sb_dev()get_filesystem()
     ĂԂƂ1łB1߂̑́Aread_super()̓ɂāA
     W[A[ĥ邽߂łA2߂̑́A}E
     gꂽCX^XɂăW[gpł邱Ƃ
     ߂̂̂łB炩ɁAe}Eg̑Ŝł̃JEg1
     邱ƂAdo_mount()͖߂OɃJE^̂łB

  2. X̏ꍇAfs_type->fs_flags & FS_REQUIRES_DEV^łȂAu
     bNfoCXւ̃t@X擾At@CVXe
     read_super()\bhƘAgăX[p[ubN𖄂
     get_sb_bdev()ĂԂƂŁAX[p[ubNBSĂ
     ܂s΁Asuper_block\̂͏At@CVXe
     W[ւextraQƂƁAɂubNfoCXւ̎QƂ𓾂邱
     ɂȂB

  3. Vvfsmount\̂蓖ĂAsb->s_mountsXgƃO[o
     vfsmntlistXgփNBvfsmount̃omnt_instances
     SĂ̓X[p[ubNɃ}EgĂCX^X
     悤ɂB mnt_listóAVXeŜ̑SẴX[p[u
     bNɑ΂āASẴCX^X邱Ƃł悤ɂ
     Bmnt_sbo͂̃X[p[ubNwAmnt_rootsb->s_root
     dentry ւ̐VQƂB

  3.6.  zt@CVXe̗: pipefs

  }EgɃubNfoCXKvȂȒP Linux t@CVXe̗
  ƂāAfs/pipe.cpipefsグ܂傤Bt@CVXȇO
  ͂ȂȒPŁAƂŏ\łB

  ______________________________________________________________________
  static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super,
          FS_NOMOUNT|FS_SINGLE);

  static int __init init_pipe_fs(void)
  {
          int err = register_filesystem(&pipe_fs_type);
          if (!err) {
                  pipe_mnt = kern_mount(&pipe_fs_type);
                  err = PTR_ERR(pipe_mnt);
                  if (!IS_ERR(pipe_mnt))
                          err = 0;
          }
          return err;
  }

  static void __exit exit_pipe_fs(void)
  {
          unregister_filesystem(&pipe_fs_type);
          kern_umount(pipe_mnt);
  }

  module_init(init_pipe_fs)
  module_exit(exit_pipe_fs)
  ______________________________________________________________________

  ̃t@CVXéA[UԂ}EgłAVXeŜň
  ̃X[p[ubN̂ݎĂ邱ƂӖFS_NOMOUNT|FS_SINGLE^
  ȂĂ܂B FS_SINGLEłt@C͓lɁAregister_filesystem()
  gēo^ƂɁAkern_mount()gă}EgȂ΂
  ȂƂӖĂ܂B́A܂ɁAinit_pipe_fs()ōs邱
  ƂłB̊֐̗B̃oÓAkern_mount()sꍇ(Ⴆ
  ΁Akmalloc()add_vfsmnt()ŎsƂȂ)ɁAt@CVXe
  o^ꂽԂŎc܂AW[͎̏sɂȂ邱ƂłB
  ́Acat /proc/filesystems Oops G[̌ɂȂ܂B(x Linus
  ɁAm点pb`𑗂Bpipefs ̓W[ƂăRpC
  łȂ߂͐^̃oOł͂ȂAW[ɂȂƂl
  ׂƎv)B

  register_filesystem()̌ʂƂāApipe_fs_typefle_systemsXgɃ
  N邱ƂɂȂ܂B܂/proc/filesystemsǂݏo
  āAFS_REQUIRES_DEVݒ肳ĂȂƂunodevvtO
  upipefsvo^Ă̂邱ƂɂȂ
  B/proc/filesystemst@ĆAVFS_tOSăT|[g
  A܂ɋ@\ׂł(āA͂̃pb`܂)B
  AgSẴ[ŨAvP[VȂȂ邽߁A
  s邱Ƃł܂B Linux J[lC^[tF[XύX
  Ă(Pɗǂ邽߂)ɂւ炸A[UԂł̌݊ɋy
  ƂȂƁALinux ͂ƂĂێIȃIy[eBOVXeƂȂA
  ԍăRpCȂő̃AvP[Vg悤ɂ̂
  B

  kern_mount()̌ʂ͎̂悤ɂȂ܂B

  1. VȖ(anonymous)foCXԍ蓖Ă
     Aunnamed_dev_in_userbg}bṽrbgݒ肳B蓖
     ĂrbgȂ΁Akern_mount()EMFILEŎsB

  2. get_empty_super()ɂāAVȃX[p[ubN\̂蓖Ă
     Bget_empty_super()֐́Asuper_blockɂĐ擪
     X[p[ubÑXgāAs->s_dev == 0ƂȂ̃Gg[
     TB
  3. t@CVXeLpipe_fs_type->read_super()\bh(
     pipefs_read_super())NA[ginodeƃ[gdentry
     ƂȂ sb->s_root蓖āAsb->s_op&pipefs_opsɂȂ悤ݒ肷
     B

  4.  kern_mount()  Vvfsmount\̂蓖āAvfsmntlist
     sb->s_mounts փNadd_vfsmnt(NULL, sb->s_root, "none") 
     ĂԁB

  5. pipe_fs_type->kern_mnt͐Vvfsmount\̂ɐݒ肳Ė
     Bkern_mount()Ԃlvfsmount\̂ɂȂĂ̂́AFS_SINGLE
     t@CVXeł}Egł邱ƂAmnt->mnt_sb
     kern_mount()̌̕Ăяo̖߂łƂĂ
     wĖ߂邽߂łB

  Ńt@CVXe͓o^Ag悤ɃJ[lɃ}E
  g܂Bpipefst@CVXẽGg|CǵApipe(2)V
  XeR[ƂȂA̓A[LeN`ˑsys_pipe()֎Ă
  ܂Aۂɂ̓A[LeN`ˑfs/pipe.c:do_pipe()֐ŏ
  ܂Bꂩdo_pipe()ĂƎv܂Bpipefs Ƃ̑ݍp
  ́Ado_pipe()get_pipe_inode()V pipefs  inode 蓖Ă邽
  ߂ɌĂяoƂɋN܂B inode ̂߂ɁAinode->i_sb
  ́Apipefs ̃X[p[ubNpipe_mnt->mnt_sb֐ݒ肳܂B
  t@C̑i_foprdwr_pipe_fopsɐݒ肳āA(inode->i_pipeɕێ
  )ǂݏ҂̐ 1 ɐݒ肳܂Bfs-private p̂֕ۑ
  ɁAʂ inode o i_pipe 闝ŔApipe  FIFO 
  R[hLĂ邽߂ƁAp̂̒̑̃ANZXpXg
   FIFO ̃t@CVXeɑ݂ł悤ɂ邽߂łB
  ͂ƂĂ C ̎głAɉ^œ܂B̂߁A
  A2.2.x J[ĺA^œĂ̂łBinode ̃tB[h
  ΂ɏ~Ă܂ƂɂȂł傤B

  pipe(2)VXeR[ɁApipe_mnt}EgCX^X̎QƃJE^
  ͑܂B

  Linux ɂĂ pCv͑Ώ́io邢STREAM pipe)ł͂ȂA
  ܂t@C̗ŁAread_pipe_fopswrite_pipe_fopsꂼ
  file->f_op ͎Ă܂B

  3.7.  fBXNt@CVXe̗:BFS

  ȒPȃfBXN Linux t@CVXe̗ƂBFSlĂ݂܂
  BBFSW[̃vAufs/bfs/inode.cɂA

       ______________________________________________________________________
       static DECLARE_FSTYPE_DEV(bfs_fs_type, "bfs", bfs_read_super);

       static int __init init_bfs_fs(void)
       {
               return register_filesystem(&bfs_fs_type);
       }

       static void __exit exit_bfs_fs(void)
       {
               unregister_filesystem(&bfs_fs_type);
       }

       module_init(init_bfs_fs)
       module_exit(exit_bfs_fs)
       ______________________________________________________________________

  ƂȂĂ܂B

  ʂfstype `}NDECLARE_FSTYPE_DEV()gāAfs_type->flags
   FS_REQUIRES_DEVɐݒ肳ABFS }Egۂ̃ubNfoCX
  Kvł邱ƂĂ܂B

  W[̏֐̓t@CVXe(BFSW[ƂĐݒ肳
  ꂽƂ̂ݑ݂)o^s֐VFSɓo^܂B

  t@CVXe̓o^sƂŁA}Egi߂邱Ƃł܂B}
  Egłfs/bfs/inode.c:bfs_read_super() ɎĂ
  fs_type->read_super()\bhN܂B̊֐͎̂悤ȏ
  s܂B

  1. set_blocksize(s->s_dev, BFS_BSIZE): ubN^foCXwƃobt@
     LbVʂđݍp悤ƂĂ邱ƂAO̏
     sKvBȂ킿AubNTCYݒ肵āA
     s->s_blocksize  s->s_blocksize_bits oʂ VFS ֒ʒm
     ̂B

  2. bh = bread(dev, 0, BFS_BSIZE): foCX̃ubNOǂ݁As->s_dev
     ʂēnB̃ubN̓t@CVXẽX[p[ubNł
     B

  3. X[p[ubNBFS_MAGICԍɑ΂ĐmFAsbvCx[
     gos->su_sbh֊i[(ۂs->u.bfs_sb.si_sbhł)B

  4. āA inode rbg}bvkmalloc(GFP_KERNEL) gĊ蓖
     āA1ɐݒ肳ŏ2SẴrbg0ɐݒ肷B
     ́Ainode 01Ɗ蓖ĂȂƂ߂łBinode 1
     [głA֘Arbg͂ꐔs1ɐݒ肳BƂ
     ́At@CVXe̓}EgƂɂ͕KÓȃ[g inode
     Ăׂ̂炾B

  5. s->s_opBs_op->read_inode()N錋
     Ƃiget()ʂāA̎_ inode LbVĂяoƂ
     łB́A(inode->i_inoinode->i_devɂ)inode 
     ȂubNēǂݍށB[g inode ̎擾s
     Ainode rbg}bvAobt@[LbV̔wɂ
     X[p[ubNobt@[āANULL ԂB[g inode
     ̓ǂݍ݂OKł΁A([gƂȂ)/ƂOdentry蓖
     āA inode ̉B

  6. āAt@CVXȇSĂ inode āA inode rbg
     }bv̊֘Arbgݒ肷邽߂ɁASēǂݍށB
     āAŌ inode ̃ItZbgŌ̃t@C̊Jn/IubN
     悤Ȃ̑̓p[^vZBǂݍފe inode  inode
     LbV iput()ʂĖ߂BAKvȏɒQƂێ
     łȂ̂B

  7. t@CVXeǂݍݐpŃ}EgȂ΁AX[p[
     ubNobt@dirtyƈAs->s_dirttOݒ肷(TODO:
     Ȃ̂? ʂ́Aminix_read_super()邩Ȃ
     AminixBFS read_super()ŃX[p[ubNĂȂ
     悤Ȃ̂)B

  8. SĂ܂s΁AVFSw̌ĂяoA܂fs/super.c:read_super()
     ցȀꂽX[p[ubNԂB

  read_super()֐Ė߂Afs/super.c:get_sb_bdev()
  get_filesystem(fs_type)Ăяoʂ VFS ̓t@CVXe
  W[ւ̎QƂƃubNfoCXւ̎QƂ𓾂܂B

  ŁAt@CVXe I/O sƂɂȂɂN邩lĂ݂
  傤Bł iget()Ă΂Ƃinodeǂ̂悤ɓǂ܂邩A
  iput()łǂ̂悤ɉ邩͌Ă܂B inode ̓ǂݍ݂́A
  ̂Ƃɍinode->i_opinode->i_fop̎OݒsƂɂȂ
  ܂Bt@C̃I[v́Ainode->i_fopfile->f_op֓`܂B

  āAlink(2)VXeR[̃R[h̒ʂ蓹݂Ă܂傤BVXe
  R[̎fs/namei.c:sys_link()ɂ܂B

  1. [UԂ̖O̓J[lԂփG[`FbNsgetname()֐
     găRs[B

  2. ̖Opath_init()/path_walk()g nameidata ɕϊ
     Adcache ƑݍpBʂ old_nd nd\̂֊i[B

  3. old_nd.mnt != nd.mntłAuNXfoCXNvEXDEVԂ
     Bt@CVXe𒴂N͂łȂALinux ł͂
     t@CVXẽ}EgꂽCX^X(邢͓̃t@C
     VXe)𒴂NłȂƉ߂ĂB

  4. V dentry ndlookup_create()ɂĊ֘AÂB

  5. ʓIvfs_link()֐Ă΂AfBNgɐVGg[
     邱Ƃł邩ǂ`FbNBāAdir->i_op->link()\b
     hĂяoB̓t@CVXeɓLfs/bfs/dir.c:bfs_link()
     ֐ĂяoƂɂȂB

  6. bfs_link()̓ł́AfBNgN悤ƂĂȂ
     `FbNAłEPERMG[ŋۂB͕Wt@C
     VXe(ext2)𓯂łB

  7. փp[֐bfs_add_entry()ĂяoĐVfBNgGg
     ̃fBNgɒǉ悤ƂB̊֐́AgpĂȂX
     bg(de->ino == 0)TđSẴGg[ĂA
     Ȃ΁A name/inode ̑΂֘AubN֏oāA dirtÿ
     (X[pubNȊO̗Dx)B

  8. AfBNgGg̒ǉA삪s邱Ƃ
     Ȃ߁Ainode->i_nlink𑝕Ainode->i_ctimeXVāAinode
     ƈꏏɃCX^XVdentryƓlɁA inode  dirty
     ƃ}[NB

  unlink()/rename()̂悤ȑ̊֘A inode A悤Ȃœ
  ܂BāA܂胁bgȂ߁AőSĂ̏ڍׂ
  ͂܂B

  3.8.  shCƃoCitH[}bg

  Linux ́AfBXÑ[UAvP[VoCi̓ǂݍ݂T
  |[gĂ܂BƖʔƂɂ́ÃoCíÃtH[}b
  gŕۑĂĂ\܂BvOɑ΂VXeR[ʂ
  Iy[eBOVXe̔́A UNIX ɌtH[}b
  g(COFFȂ)G~[gAɑ̃^Cv(Solaris, UnixwareȂ)
  ̃VXeR[̐U镑G~[g邽߂ɁAKvȂ΁AW
  (Linux ̐U镑W)O邱Ƃł܂BꂪAsh
  CƃoCitH[}bgKvɂȂ闝RɂȂĂ܂B

  e Linux ̃^XŃAtask_struct(p->personality)̂Ȃɂꂼ̃p[
  \ieBĂ܂B(ȃJ[lǉpb`ł܂)
  p[\ieBɂ́AFreeBSDASolarisAUnixWareAOpenServer̃T|[
  g܂݁Aɑ̃W[ȃIy[eBOVXe܂B
  current->personality ̒l2̕ɕ܂B

  1. ʂ3oCg - oOG~[V: STICKY_TIMEOUTS,
     WHOLE_SECONDSȂ

  2. ʂ1oCg - p[\ieBɌŗLȔԍ

  p[\ieB̕ύXɂA̓Iy[eBOVXeVXe
  R[舵@ς邱Ƃł܂BƂ΁ASTICKY_TIMEOUT
  current->personality֗^邱ƂŁAselect(2)VXeR[́Ac
  Ԃۑ邩ɁAŌ̈(^CAEg)̒lێ܂Bv
  O̒ɂ(Linuxɂ͂Ȃ)oÔIy[eBOVXeɈˑ
  oÔ݂̂邽߁A\[XR[hłoOC
  Ȃꍇ̂߂ɁALinux ̓oOG~[g@񋟂Ă
  łB

  shĆAp[\ieB̉ɂA̃W[Ƃ
  Ă܂Bʏ̎shC͈̃p[\ieB
  Ă܂AȂɂ́AقǑȂ𖞂Ƃň̃W[
  ̒Ɂuṽp[\ieB邱Ƃł܂B

  shCkernel/exec_domain.cɎA2.4 J[l 2.2.x 
  犮Sɏ܂BT|[gĂp[\ieB̎ނɉA
  J[l݃T|[gĂshC̃Xg
  ́A/proc/execdomainst@CǂݏoƂœ邱Ƃł
  BPER_LINUX shĆAIɓǂݍ܂郂W[Ƃ
  ł܂B

  [UC^[tF[X́Apersonality(2)VXeR[ʂāA݂
  vZX̃p[\ieBݒł悤ɂȂĂ܂B邢́A
  ݂Ȃp[\ieB 0xffffffff ł
  current->personalityԂ܂B炩ɂ̃VXeR[̐U
  ́Ap[\ieBƂ͓ƗłB

  shCo^̃J[lC^[tF[X2̊֐ɂȂĂ܂B

  o  int register_exec_domain(struct exec_domain *): ǂݏXsb
     Nexec_domain_lockɂ鏑ݕی̂ƁAPNXg
     exec_domains֎shCN邱ƂŁAo^B
     0ԂAsȂ0ƂȂB

  o  int unregister_exec_domain(struct exec_domain *): exec_domiansX
     g͂ƂɂshCo^Bo^Ɠ
     lAexec_domian_lockXsbN݃[hŗpB
     0ԂB

  exec_domains_lockǂݏbNł闝ŔAo^Ɠo^v̂
  XgAcat /proc/filesystems
  fs/exec_domain.c:get_exec_domain_list()ĂԂƂAXg̓
  ݏos߂łBVshC̓o^ɂAulcall7 nh
  vƃVOiԍ̕ϊ}bv`܂BہAABIpb`́A
  shC̍lgāA(\PbgIvV\Pbg^CvA
  AhXt@~BG[ԍ}bvƂ)ǉ̏悤ɂ
  Ă܂B

  oCitH[}bg͓悤ɎĂ܂B܂APNX
  gtH[}bgfs/exec.cŒ`AǂݏbNbinfmt_lockŕی삵
  ܂Bexec_domains_lock̂悤ɁAbinfmt_locḱAoCitH[}bg
  o^o^̂ƂقƂǂ̏ꍇɓǂݍ݂݂̂ɂȂĂ܂B
  VoCitH[}bgo^邱ƂŁAcore_dump()ł̂Ɠ
  lɁAVload_binary/load_shlib()֐ɂāAexecve(2)VXe
  R[͋@\g܂Bload_binary()\bhAexecve(2)VXe
  R[Ădo_execve()search_binary_handler()ɂČĂ
  ĂƂɁAload_shlib()\bh͌Âuselib(2)VXeR[
  Ă̂ݎg܂B

  vZX̃p[\ieB́A኱̔I@đΉtH[
  }bgload_binary()\bhǂݍ܂ꂽoCi[tH[}bg
  Č肳܂B UnixWare7oCi肷ƂẮA
  elfmark(1)[eBeBgāAELF̂փb_[e_flagsɁA}WbN
  l 0x314B4455ɐݒ肵A܂B̃}WbNĺAELF̃[h
  oAcurrent->personalityPER_UW7ݒ肵܂B

  xp[\ieB(ƁA]current->exzec_domain)΁AVXe
  R[͎̂悤Ɏ舵܂BvZX lcall7 Q[g߂g
  VXeR[𔭍sƂ܂傤B͐
  arch/i386/kernel/entry.SENTRY(lcall7)Ɉڂ܂BȂȂ炱
  ́Aarch/i386/kernel/traps.c:trap_init()ɏĂ邽߂łBK
  ȃX^bN蓖Ă̕ϊ̂ƁAentry.S:lcall7current 
  exec_domain ւ̃|C^ƁA(AZu4Ƀn[hR[hĂ
  Astruct exec_domainC̒`ŁAhandleroړłȂ̂ł
  )exec_domain lcall7 nh̃ItZbg𓾂āAփWv
  ܂BłACł́Â悤ɂȂ܂B

       ______________________________________________________________________
       static void UW7_lcall7(int segment, struct pt_regs * regs)
       {
              abi_dispatch(regs, &uw7_funcs[regs->eax & 0xff], 1);
       }
       ______________________________________________________________________

  abi_dispatch()́A֐|C^̕\ւ̃bp[łA͂̃p[\
  ieB̃VXeR[uw7_funcŝɂȂĂ܂B

  4.  Linux y[WLbV

  ̏͂ł́ALinux 2.4̃y[WLbVɂĐ܂By[W
  LbV́AOĂ悤ɁAy[W̃LbVłBUNIX
  ̐Eł̓y[WLbV̍l SVR4 UNIX ̓oɂAf[^I/O
  ł̃obt@[LbVu悤ɂėǂg悤ɂ
  ܂B SVR4 y[WLbVł́At@CVXẽf[^Lb
  VƂĂ̂ݎgĂA vnode \̂ƃt@C̃It
  ZbgnbVp[^ƂĎgĂ܂A Linux ̃y[WLb
  V͂ʓIɐ݌vĂ邽߁A(ȉŐ)\
  address_space ڂ̃p^ƂĎg܂B Linux y[WLb
  V́AAhXԂ̕\L@ɋѕtĂ邽߁Ay[WLb
  V̓𗝉ɂ́AȂƂ address_space ̊{IȗK
  vłB address_space ̓\tgEGA MMU ̈ŁAIuWFNg (
  Ⴆ inode) ׂ̂Ẵy[W𑼂̑Ήl(T^Iɂ͕fBXN
  ubN)ւƑΉÂĂ܂B\ address_spece 
  include/linux/fs.h ňȉ̂悤ɒ`Ă܂B

  ______________________________________________________________________
          struct address_space {
                  struct list_head        clean_pages;
                  struct list_head        dirty_pages;
                  struct list_head        locked_pages;
                  unsigned long           nrpages;
                  struct address_space_operations *a_ops;
                  struct inode            *host;
                  struct vm_area_struct   *i_mmap;
                  struct vm_area_struct   *i_mmap_shared;
                  spinlock_t              i_shared_lock;
          };
  ______________________________________________________________________

  address_spaces ̓@𗝉ɂ́Ãöꕔ邾
  łł傤B clean_pagesAdirty_pagesAlocked_pages ́A
  address_space ɑĂ cleanAdirtyAlocked ̂ꂼ̃y[Wɂ
  Ă̑oNXgłB܂A nrpages ͂ address_space ̑
  y[WɂȂĂ܂B a_ops ́ÃIuWFNg̃\bh`
  ĂA host ́A address_space  inode ւ̃|C^ƂȂ
  Ă܂B NULL ɂȂ܂BႦ΁Aswapper  address_space
  ̏ꍇ (mm/swap_state.c) ɂ܂B

  clean_pages  dirty_pagesA locked_pagesA nrpages ̗p@͎
  Ǝv܂̂ŁA address_space_operations \݂̂Ă
  B͓փb_t@Cɒ`ĂA

       ______________________________________________________________________
               struct address_space_operations {
                       int (*writepage)(struct page *);
                       int (*readpage)(struct file *, struct page *);
                       int (*sync_page)(struct page *);
                       int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
                       int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
                       int (*bmap)(struct address_space *, long);
               };
       ______________________________________________________________________

  ƂȂĂ܂B

  address_space  y[WLbV̊{IȍĺA->writepage
   ->readpageɒڂKv܂BAۂɂ
  ->prepare_write ->commit_writeɂڂKv܂B

  炭̖O̘Az address_space_operations \bh
  s邩AĂ邱Ƃłł傤BłA኱̒ǉ͕K
  vłBt@CVXef[^ I/O ł̎gꂩ́Ay[WLbV
  ֒ʂ鉤łÂɂĂłB̑UNIXñIy
  [eBOVXeƈႢALinux ł́Ay[WLbVɂf[^
  I/O ɑ΂ĈʓIȃt@C( SYSV  vnode ̃TuZbg)
  \łB́Aread/write/mmap ɂĂ̓f[^ڃt@CVXe
  ƍpA\Ȍy[WLbVւ݂̏ǂݍ݂ɂčs
  邱ƂӖĂ܂By[WLbV́A[UɂȂ
  y[Wǂݍ݂ꍇ⃁ȂꍇɃfBXNփf[^
  ݂ꍇɁAf[^ۂ̒჌xt@CVXe擾Ȃ
  ΂Ȃ܂B

  ǂݍ݃pXł́AʓIȃ\bhł́AŏɕKvƂinode/Cfb
  NX^vɑΉy[W悤Ƃ܂B

       hash = page_hash(inode->i_mapping, index);

  Ăǂ̃y[Wۂɑ݂Ă邩eXg܂B

       hash = page_hash(inode->i_mapping, index); page =
       __find_page_nolock(inode->i_mapping, index, *hash);

  ݂ȂƂ͐Vt[y[W蓖ăy[WLbV֒ǉ
  ܂B

       page = page_cache_alloc(); __add_to_page_cache(page, mapping, index,
       hash);

  y[WnbVꂽA->readpage AhXԑgāAy[W
  ۂɃf[^Ŗ(t@CinodẽI[vCX^X)܂B

       error = mapping->a_ops->readpage(file, page);

  ŌɃf[^[UXy[XɃRs[܂B

  t@CVXeɏɂ2̃pX܂B1̓}bv(mmap)ɏ
  ނƁA write(2) ̂悤ȃVXeR[p邱Ƃ
  Bmmap ̏ꍇƂĂVvȂƂA܂ŏɎグ邱Ƃ
  ܂B[U}bvύXƂAVMTuVXe̓y[W dirty
  ƃ}[N܂B

       SetPageDirty(page);

  obNOhł̊ƂāA邢̓ȂȂ̂𗝗RƂ
  āAy[W悤Ƃ bdflush J[lXbh́Adirty ƃ}[
  Nꂽy[W ->writepage ĂڂƂ܂B->writepage \bh
  ́Ay[W̓efBXNɏoAy[WȂ΂Ȃ܂B

  2߂̏݃pX́A ƂĂւ񕡎GłB[Uފe
  y[Wɑ΂āA{IɈȉ̂Ƃs܂(R[h̑Ŝ
  mm/filemap.c:generic_file_write() Q)B

       page = __grab_cache_page(mapping, index, &cached_page); map-
       ping->a_ops->prepare_write(file, page, offset, offset+bytes);
       copy_from_user(kaddr+offset, buf, bytes); mapping->a_ops->com-
       mit_write(file, page, offset, offset+bytes);

  ŏɁAnbVꂽy[W悤Ƃ邩Vy[W蓖
  悤Ƃ܂BāA->prepare_write AhXԃ\bhĂяoA
  [Uobt@J[lɃRs[AčŌ ->commit_write
  \bhĂяo܂B炭 ->prepare_write  ->commit_write
  ́A->readpage  ->writepage ͊{IɈقȂ̂Ɍł
  B͕ I/O ۂɋ߂ꂽł͂ȂA[Ut@C
  ύXƂɂ͂Ăяo邩łB@2(
  ͂ȏ?)܂B߂ page->buffers |C^
  try_to_free_buffers(fs/buffers.c) ŎgĂ buffer_heads Ŗ߂
  ƂŁA IO ̒x Linux obt@[LbVg܂B
  ̕@́Ay[W dirty ɒPɐݒ肵ȂSĂ ->writepageɂ܂
  邱ƂłBy[W\̂ɗLȃrbg}bvĂ邽
  ߁APAGE_SIZE菬granualityĂt@CVXeł͓
  ܂B

  5.  IPC@\

  {͂łLinux 2.4 J[lŎĂ IPC @\̃Z}tHAL
  уbZ[WL[ɂċLq܂Bl̐߂ō\Aŏ
  ̎O̐߂ł``Z}tH'' ``bZ[WL[''A``L''
  ɎグāAC^[tF[XƃT|[g֐܂B܂A ``
  ''̐߂ł́AO̋@\ŋL鋤ʊ֐Qƃf[^\
  B

  5.1.  Z}tH

  ̐߂ŐĂ֐̓[Ux̃Z}tH@\̎ɂȂĂ
  B̎̓J[lXsbNƃJ[lZ}tH̗pɗ
  邱Ƃɒӂ܂傤B邽߁AJ[l̃Z}tHQƂ
  Ƃ́uJ[lZ}tHvƌĂԂƂɂ܂B̑̒PɁuZ}
  tHvƂƂ́A[Ux̃Z}tHwƂɂ܂B

  5.1.1.  Z}tHVXeR[̃C^[tF[X

  5.1.1.1.  sys_semget()

  SĂsys_semget()ւ̌ďóAJ[lO[o``sem_ids.sem''
  J[lZ}tHŕی삳܂BVZ}tH̃ZbgȂ΂
  Ȃꍇ́A``newary()'' ֐Ă΂āAVZ}tHZbg̍쐬
  Ə܂BĐVZbgID ďoɖ߂܂B

  L[̒l̃Z}tHZbgɑ΂Ĕsꂽ̂ꍇ
  ́A``ipc_findkey()'' ĂяoAZ}tHfBXNv^z
  CfbNX܂Bp[^ƌďõp[~bV́AZ}
  tH̃ZbgIDԋpOɊmF܂B

  5.1.1.2.  sys_semctl()

  ``IPC_INFO'' ``SEM_INFO''  ``SEM_STAT'' R}hɂẮAK
  vȊ֐s ``semctl_nolock()'' Ăяo܂B

  ``GETALL''A ``GETVAL''A ``GETPID''A``GETNCNT''A ``GETZCNT''A
  ``IPC_STAT''A ``SETVAL''A``SETALL'' R}hɂẮAKvȊ֐
  s ``semctl_main()'' Ăяo܂B

  ``IPC_RMID''``IPC_SET'' R}hɂẮAKvȊ֐s
  ``semctl_down()'' Ăяo܂B̉Z̊Ԃ́AO[o
  ``sem_ids.sem'' J[lZ}tHێ܂B

  5.1.1.3.  sys_semop()

  ďo̗LmFAZ}tH̑f[^[UԂ
  obt@փRs[܂Bꎞobt@ő傫\ł΃X
  ^bNobt@g܂Bs\ȂA傫obt@蓖Ă
  BZ}tH̑f[^̃Rs[IɁAO[oȃZ}tHX
  sbNbN܂Bă[Uw肵Z}tHZbgIDmF
  ܂BZ}tHZbgւ̃p[~bVLmF܂B

  [Uw肵Z}tH삪Sĉ͂܂B̏̊ԁAJEg
   SEM_UNDO tOZbgSĂ̑ێ܂BZ}tHlZ
  鑀̂Ƃɂ́A decreasetOݒ肳܂BāAZ}tH
  lύX(܂葝͌)̑SĂɂāAalter tO
  ݒ肳܂BĕύXeZ}tH̒lLmF܂B

  Ȃ̂ꂩZ}tH̏Ԃω̂ł΁A
  ̃Z}tHZbgɊ֘A undo \̂ ݂̃^XN undo Xg
  T܂B̌̊ԁA undo \̂̔Cӂ̃Z}tHZbgID
  -1 łƕȂ΁A``freeundos()'' Ă΂A undo \̂
  ăXg폜܂BAundo \̂̃Z}tHZbg
  ɂČȂ΁A ``alloc_undo()'' Ă΂Ċ蓖Ăя
  s܂B

  Ȃs邽߂  ``try_atomic_semop()'' ֐ do_undo p
  [^ 0 ɂČĂяo܂BԂĺA삪ꂽs
  A邢̓ubN̕KvߎsȂĂ
  BeX̏ꍇȉɎ܂B

  5.1.1.3.1.  ubNZ}tH

  ``try_atomic_semop()'' ֐́AȂSĂ̑삪ƂɁA[
  Ԃ܂B̏ꍇɂ́A``update_queue()'' ĂяoAZ}tH
  ZbĝۗĂZ}tH̑̃L[𑖍āAub
  N̕KvȂx~^XNN܂B̏ɂāȀꍇ
  sys_semop() VXeR[̎s܂B

  5.1.1.3.2.  Z}tH̎s

  A``try_atomic_semop()''̒lԂꍇAQԂɑ
  ƂɂȂ܂B̏ꍇA͑SĎs܂B́AZ}tH
  AȃZ}tHlɂȂAIPC_NOWAITɃ}[NÂꂽ삪s
  łȂꍇɋN܂BG[Ԃ͂̌Asys_semop()̌ďo
  ɕԂ܂B

  sys_memop()߂OɁAZ}tHZbgۗ̕ꂽZ}tH
  L[𑖍邽 update_queue() ďoAubN̕Kv̂Ȃ
  x~^XNN܂B

  5.1.1.3.3.  ubLOZ}tH

  ``try_atomic_semop()''֐́AZ}tḦubNAA
  Z}tH삪sȂꍇɂ 1 Ԃ܂B̏ꍇAV
  ``sem_queue''̗vf̃Z}tH܂߂ď܂B
  Ȃ̂ꂩZ}tH̏Ԃωł΁AV
  L[̗vf̓L[̖ɒǉ܂BłȂΐVL[
  ̗vfL[̐擪ɑ}܂B

  ݂̃^XNsemsleepingvf́A^XN``sem_queue'' vfŋx~
  Ă邩ǂĂ܂B݂̃^XN TASK_INTERRUPTIBLE 
  }[NA``sem_queue''sleepervf̃^XNx~Ă邱Ƃ
  ߐݒ肳܂BăO[oZ}tHXsbNA
  ݂̃^XNx~邽schedule()Ăяo܂B

  NꂽƂAȂNꂽAǂ̂悤ɔׂ𔻒f邽
  ߁A^XN̓O[oZ}tHbNăbN܂Bȉ̂悤ȏꍇ
  ܂B

  o  AZ}tHZbg폜ꂽȂAVXeR[́AEIDRMŎs
     B

  o  A ``sem_queue'' \̂ status vf 1 ɐݒ肳ĂA
     ^XN̓Z}tHĂю݂邽߂ɋNꂽB1
     x``try_atomic_semop()'' ďoÃZ}tH̎ssB
      try_atomic_sweep()  1 ԂȂA^XN͏L̂悤ɍēxu
     bNȂ΂ȂȂBłȂΐ 0 ߂Ă
     Asꍇ͓K؂ȃG[R[hԂB

     sys_semop() ߂OɁAcurrent->semsleeping NAB
     āA ``sem_queue''́AL[폜Bw肳ꂽZ}tH
     삪ύX̑(A)ȂA``update_queue()'' AZ
     }tHZbgۗ̕ꂽZ}tH̃L[𑖍邽߂ɌĂяo
     AubN̕Kv̂Ȃx~^XNNB

  o  A``sem_queue'' \̂ status vf 1  uȂv
     ``sem_queue'' vfL[͂Ȃ΁A^XN͊荞݂
     NꂽƂɂȂB̏ꍇVXeR[͎s EINTR 
     B߂O current->semsleeping ̓NAA``sem_queue''
     L[폜BɁAύX鑀삪
     ``update_queue()'' ĂяoB

  o  A``sem_queue'' \̂ status vf1ɐݒ肳āw
     xA``sem_queue'' vfL[폜ĂȂ΁AZ}tH
     ͊ ``update_queue()'' ɂsĂBL[statuśA
     0ɁAsɕ̃G[R[hɂȂAVXeR[̕Ԃ
     lɂȂB

  5.1.2.  Z}tHƎɃT|[g\

  ȉ̍\̂́AZ}tH̃T|[gɓɎg܂B

  5.1.2.1.  struct sem_array

       ______________________________________________________________________
       /* One sem_array data structure for each set of semaphores in the system. */
       struct sem_array {
           struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
           time_t sem_otime; /* last semop time */
           time_t sem_ctime; /* last change time */
           struct sem *sem_base; /* ptr to first semaphore in array */
           struct sem_queue *sem_pending; /* pending operations to be processed */
           struct sem_queue **sem_pending_last; /* last pending operation */
           struct sem_undo *undo; /* undo requests on this array * /
           unsigned long sem_nsems; /* no. of semaphores in array */
       };
       ______________________________________________________________________

  5.1.2.2.  struct sem

       ______________________________________________________________________
       /* One semaphore structure for each semaphore in the system. */
       struct sem {
               int     semval;         /* current value */
               int     sempid;         /* pid of last operation */
       };
       ______________________________________________________________________

  5.1.2.3.  struct seminfo

       ______________________________________________________________________
       struct  seminfo {
               int semmap;
               int semmni;
               int semmns;
               int semmnu;
               int semmsl;
               int semopm;
               int semume;
               int semusz;
               int semvmx;
               int semaem;
       };
       ______________________________________________________________________

  5.1.2.4.  struct semid64_ds

       ______________________________________________________________________
       struct semid64_ds {
               struct ipc64_perm sem_perm;             /* permissions .. see
       ipc.h */
               __kernel_time_t sem_otime;              /* last semop time */
               unsigned long   __unused1;
               __kernel_time_t sem_ctime;              /* last change time */
               unsigned long   __unused2;
               unsigned long   sem_nsems;              /* no. of semaphores in
       array */
               unsigned long   __unused3;
               unsigned long   __unused4;
       };
       ______________________________________________________________________

  5.1.2.5.  struct sem_queue

       ______________________________________________________________________
       /* One queue for each sleeping process in the system. */
       struct sem_queue {
               struct sem_queue *      next;    /* next entry in the queue */
               struct sem_queue **     prev;    /* previous entry in the queue, *(q->pr
       ev) == q */
               struct task_struct*     sleeper; /* this process */
               struct sem_undo *       undo;    /* undo structure */
               int                     pid;     /* process id of requesting process */
               int                     status;  /* completion status of operation */
               struct sem_array *      sma;     /* semaphore array for operations */
               int                     id;      /* internal sem id */
               struct sembuf *         sops;    /* array of pending operations */
               int                     nsops;   /* number of operations */
               int                     alter;   /* operation will alter semaphore */
       };
       ______________________________________________________________________

  5.1.2.6.  struct sembuf

       ______________________________________________________________________
       /* semop system calls takes an array of these. */
       struct sembuf {
               unsigned short  sem_num;        /* semaphore index in array */
               short           sem_op;         /* semaphore operation */
               short           sem_flg;        /* operation flags */
       };
       ______________________________________________________________________

  5.1.2.7.  struct sem_undo

       ______________________________________________________________________
       /* Each task has a list of undo requests. They are executed automatically
        * when the process exits.
        */
       struct sem_undo {
               struct sem_undo *       proc_next;      /* next entry on this process */
               struct sem_undo *       id_next;        /* next entry on this semaphore set */
               int                     semid;          /* semaphore set identifier */
               short *                 semadj;         /* array of adjustments, one per
        semaphore */
       };
       ______________________________________________________________________

  5.1.3.  Z}tHT|[g֐

  ȉ̊֐͓ɃZ}tH̃T|[ĝ߂Ɏg܂B

  5.1.3.1.  newary()

  newary() ́AVZ}tHZbgɕKvƂȂ郁蓖Ă邽
  ɁA ``ipc_alloc()''𗘗pĂ܂BāAZ}tHZbgLqq
  Zbg̊eZ}tH̑SĂɏ\ȃ蓖Ă܂B蓖Ăꂽ
  ̓NAAZ}tHZbgfBXNv^̍ŏ̗vf̃AhX
  A``ipc_addid()'' ւƓn܂B``ipc_addid()'' ́AVZ}tH
  ZbgLqq̃Ggz\񂵁Af[^(``struct kern_ipc_perm'')
  ܂BO[oused_sems ϐ́AVZbg̃Z}tH
  XVāAVZbĝ߂̃f[^(``struct kern_ipc_perm'')̏
  ܂B̃ZbgɊւ鑼͈̏ȉ̒ʂłB

  o  Zbgsem_base vfAVɊ蓖Ăꂽf[^(``struct
     sem_array'')̂Ƃ̃AhXɏB́AZbg
     ŏ̃Z}tH̏ꏊɑΉB

  o  sem_pendingL[́AɏB

  ``ipc_addid()''̌ďoɑSĂ̑́AO[oZ}tHXs
  bNێԂŎs܂BO[oZ}tHXsbNA
  bNɁAnewary() ́A(sem_buildid()oR)``ipc_buildid()'' 
  ďo܂B̊֐́AZ}tHZbgfBXNv^̃CfbNXg
  pAj[N ID 𐶐܂BāAnewary() ̌ďoɖ߂
  B

  5.1.3.2.  freeary()

  freeary()  ``semctl_down()''ɂČĂяoAȉɗ񋓂@\
  s܂BO[oȃZ}tHXsbNbNꂽԂŌĂяo
  AXsbNꂽԂŖ߂܂B

  o  Z}tHZbg ID 폜Z}tHZbgւ̃|C^邽
     ߁A ``ipc_rmid()''  ֐A(sem_rmid()bp[oR)Ăяo
     B

  o  Z}tHZbg undo Xg̗LmFB

  o  SĂۗ̕vZXNAEIDRM ̎sNB

  o  gpĂZ}tH̃JE^́A폜Zbg̃Z}tH
     炳B

  o  Z}tHZbgɊ蓖ĂꂽB

  5.1.3.3.  semctl_down()

  semctl_down() ́A semctl()VXeR[ ``IPC_RMID'' 
  ``IPC_SET'' 񋟂܂BZ}tHZbgIDƃp[~bV́A
  ̑ɐ旧ĊmFAǂ̏ꍇÅԂ̓O[oZ}
  tHXsbNێ܂B

  5.1.3.3.1.  IPC_RMID

  IPC_RMID ł́AZ}tHZbg̍폜s߁A ``freeary()''
  яo܂B

  5.1.3.3.2.  IPC_SET

  IPC_SET ł́AZ}tHZbguidAgidAmodectime vfXV
  ܂B

  5.1.3.4.  semctl_nolock()

  semctl_nolock()  ``sys_semctl()'' ĂяoAIPC_INFOASEM_INFO
   SEM_STAT @\s܂B

  5.1.3.4.1.  IPC_INFO  SEM_INFO

  IPC_INFO  SEM_INFO ́AՎ ``seminfo'' obt@AύX
  ȂZ}tH̓vf[^ǂݍ܂܂BāAO[o
  sem_ids.sem J[lZ}tHmۂA ``seminfo'' \̂ semusz
   semaem vf^ꂽ(IPC_INFO ܂ SEM_INFO)R}hɏ]XV
  ܂BVXeR[̕ԂĺAZ}tHZbgID̍őlɂȂ܂B

  5.1.3.4.2.  SEM_STAT

  SEM_STAT ́AՎ``semid64_ds''obt@܂B̌AO
  [oZ}tHXsbNێAsem_otimeAsem_ctimesem_nsems
  ̒lobt@ɃRs[܂B̃f[^͂̌テ[UԂɃRs[
  ܂B

  5.1.3.5.  semctl_main()

  semctl_main() ́A ``sys_semctl()'' ɂĂяoAȉ̐߂Ŏ
  鑽̃T|[g@\s܂BSĂ̑ɐ悾
  āAsemctl_main() ́AO[oZ}tHbNbNAZ}tHZb
  gIDƃp[~bV̗LmF܂BXsbN͖߂Oɉ
  ܂B

  5.1.3.5.1.  GETALL

  GETALL ́Ã݂Z}tHlꎞIȃJ[lobt@֓ǂݍ݁A
  [UԂփRs[܂BZ}tHobt@΁AȃX
  ^bNobt@g܂BłȂ΁AXsbNꎞIɗ
  A傫ȃobt@mۂ܂BZ}tHlꎞobt@փRs[
  ԁAXsbNێ܂B

  5.1.3.5.2.  SETALL

  SETALL ́AZ}tHl[UԂJ[l̈ꎞobt@փR
  s[ǍZ}tHZbgփRs[܂Bꎞobt@փ[UԂ
  lRs[ԁAѐlmFԁAXsbN𗎂Ƃ
  BZ}tHZbg΁AX^bNobt@gAł
  Α傫ȃobt@mۂ܂Bȉ̑Z}tHZbg֍s
  ԁAXsbNĎ擾Aێ܂B

  o  Z}tHlZ}tHZbgփRs[B

  o  Z}tHZbĝ߂̃AhDL[ɂZ}tHC̓NA
     B

  o  Z}tHZbgsem_ctime lݒ肳B

  o  ``update_queue()'' ֐ĂяoAۗĂ semops ̃L[
     ASETALL ̌ʂƂĊł^XNTBubN
     ĂȂSĂۗ̕^XNNB

  5.1.3.5.3.  IPC_STAT

  IPC_STAT ł́Asem_otimeAsem_ctimesem_nsems lX^bNob
  t@փRs[B̃f[^́ǍXsbN𗎂ƂĂ烆[U
  ԂփRs[B

  5.1.3.5.4.  GETVAL

  G[̂ȂꍇAGETVALł́AVXeR[̕ԂlɎw肵Z}tH
  ̒lݒ肳B

  5.1.3.5.5.  GETPID

  G[̂ȂꍇAGETPIDł́AVXeR[̕ԂlɃZ}tHł̍Ō
  ̑ɑΉ pid ݒ肵܂B

  5.1.3.5.6.  GETNCNT

  G[̂ȂꍇAGETNCNT ł̓VXeR[̕ԂlɁAZ}tH 0
  ɂȂ̂҂ĂvZX̐ݒ肵܂B̐l
  ``count_semncnt()'' ֐vZ܂B

  5.1.3.5.7.  GETZCNT

  G[̂ȂꍇAGETZCNT ł̓VXeR[̕ԂlɁAZ}tH0
  ݒ肳̂҂ĂvZX̐ݒ肵܂B̐l
  ``count_semzcnt()'' ֐vZ܂B

  5.1.3.5.8.  SETVAL

  VZ}tHl̗LmFƁAȉ̋@\s܂B

  o  ̃Z}tH̏CȂǂAundo L[B

  o  Z}tHlɁA^ꂽlZbgB

  o  Z}tHZbg sem_ctime lXVB

  o  ``update_queue()''֐Ă΂Aۗ semops L[𑖍āA
     ``SETVAL'' ̌ʂƂĊł^XNB

  5.1.3.6.  count_semncnt()

  count_semncnt() ́AZ}tHl 0 菬Ȃ̂҂Ă^XN
  𐔂܂B

  5.1.3.7.  count_semzcnt()

  count_semzcnt() ́AZ}tHl 0 ɂȂ̂҂Ă^XN𐔂
  ܂B

  5.1.3.8.  update_queue()

  update_queue() ́AZ}tHZbgۗ̕ semops L[𑖍āA
  ``try_atomic_semop()'' ĂяoAǂ̃Z}tH̃V[PX
  𔻒f܂BL[vf̏ԂɂAubNꂽ^XN
  łɋNĂ邱ƂĂÂƂ͂̃L[vf
  XLbv܂BL[̗̂̑vfł́Aq-alter tO
  ``try_atomic_semop()''  undo p[^ƂēnAύX̑삩
  ߂OɎs鑀\܂B

  Ȃ삪ubNȂAupdate_queue() ͈ؕύX邱
  ƂȂ߂܂B

  Z}tḦȃZ}tHlNAIPC_NOWAIT
  ƃ}[NĂ鑀삪łȂȂ΁AȂ͎s
  B̂悤ȏꍇ́AZ}tHɂubNĂ^XN͋N
  AL[̏ԂƂēK؂ȃG[R[hݒ肳܂BL[vf
  L[폜܂B

  Ȃ삪ύX𐶂ȂȂ΁A``try_atomic_semop()''  undo
  p[^Ƃ 0 n܂B̑삪΁A͊
  ƌȂāAL[폜܂BubNꂽ^XNN
  AL[vfstatus悤ݒ肳܂B

  Zbg̑삪Z}tH̒lύXꍇŁAłȂA
  ubNKv̂Ȃx~^XNN܂B삪s
  ĂAL[vfL[폜邱Ƃ͂܂BZ}tH
  ́ANꂽ^XNɂĎs܂B

  5.1.3.9.  try_atomic_semop()

  try_atomic_semop() ́A``sys_semop()'' ``update_queue()'' ɂĂ
  oAÃZ}tH삪SĐ邩ǂf܂B́Ae
  ̎s݂邱ƂɂĔfs܂B

  ubNꂽɑȂAvZX̓A{[gASĂ̑
  ͍߂܂BIPC_NOWAIT ݒ肳ĂȂ -EAGAIN Ԃ
  ܂BłȂ 1 ԂAÃZ}tH삪ubNꂽ
  Ƃ܂B

  Z}tHlVXe̐zĕύXȂ΁ASĂ͍̑
  ߂A -ERANGE Ԃ܂B

  V[PX̑SĂ̑삪ĂAdo_undop[^0łȂ
  ΁ASĂ̑삪߂āA0 Ԃ܂B do_undo p[^
   0 ȂASĂ̑삪AIɎcAZ}tHZbg
  sem_otime oXV܂B

  5.1.3.10.  sem_revalidate()

  sem_revalidate() ́AO[oZ}tHXsbNꎞIɗƂ
  AēxbNȂ΂ȂȂƂɌĂяo܂B 
  A``semctl_main()''  ``alloc_undo()'' ɂČĂяo܂BZ}
  tHIDƃp[~bV̗LmFAǂ΃O[oZ}tHXs
  bNbNĖ߂܂B

  5.1.3.11.  freeundos()

  freeundos() ́AvZX undo Xg𑖍Avꂽ undo \
  T܂B΁Aundo \̂̓Xg폜A
  ܂BāAvZXXg̎ undo \̂ւ̃|C^Ԃ
  B

  5.1.3.12.  alloc_undo()

  alloc_undo() ́AO[oZ}tHXsbNlČĂ΂邱
  ҂Ă܂BG[ꍇ́AXsbNĖ߂
  B

  O[oZ}tHXsbNA ``sem_undo''\̂ƁAZb
  g̊eZ}tH̏Cl̔z̗ɏ\ȃmۂ邽
  ߁Akmalloc()Ăяo܂B΁AO[oXsbN
  ``sem_revalidate()''ĂяoƂōĊmۂ܂B

  V semundo \̂A̍\̂̃AhXďo
  ė^ꂽAhX֊i[܂BV undo \̂́Ã݂^
  XN undo Xg̐擪ֈʒu܂B

  5.1.3.13.  sem_exit()

  sem_exit() ́Ado_exit() ɂĂяoA݂^XN̑SĂ undo
  CsӔC܂B

  ݂̃vZXZ}tHŃubNĂȂA O[oZ}
  tHXsbNێ ``sem_queue''Xg폜܂B

  Č݂̃^XN̂߂ undo XgAXg̊evf̏
  ɃO[oZ}tHXsbN̎擾ƉsAȉ̑
  s܂Bȉ̑́Ae undo vfƂɎs܂B

  o  undo \̂ƃZ}tHZbg ID ɂėLmFB

  o  ֘AZ}tHZbg undo XgA undo \̂ւ̎Q
     AXg炻폜B

  o  undo \̂ɎĂCZ}tHZbg֓KpB

  o  Z}tHZbgsem_otime p[^XVB

  o  ``update_queue()'' ĂяoAۗ semops ̃L[𑖍
     āAAhD̎šʂƂăubNKv̂Ȃx~^
     XNNB
  o  undo \̂B

  Xg̏Ȃ΁Acurrent->semundo ̒lNA܂B

  5.2.  bZ[WL[

  5.2.1.  bZ[WVXeR[C^[tF[X

  5.2.1.1.  sys_msgget()

  sys_msgget()ւ̃R[Ŝ́AO[obZ[WL[Z}
  tH(``msg_ids.sem'')ɂی삳Ă܂B

  VbZ[WL[Ȃ΂ȂȂꍇA``newque()''֐
  яoAVbZ[WL[̍쐬ƏsAVL[ID
  ďoɕԂ܂B

  ^ꂽL[̒l̃bZ[WL[ւȂA
  ``ipc_findkey()''ĂяoAO[obZ[WL[fXNv^
  z(msg_ids.entries)̑ΉCfbNXT܂Bďõp
  [^ƃp[~bV́AbZ[WL[ID߂OɊmF܂B
  ƊmF́AO[obZ[WL[XsbN(msg_ids.ary)
  ێꂽԂōs܂B

  5.2.1.2.  sys_msgctl()

  sys_msgctl()֓np[^́AbZ[WL[ID(msqid)A
  (cmd)A^Cv``msgid_ds''̃[Uԃobt@ւ̃|C^(buf)łB
  6 ̑삪̊֐Œ񋟂Ă܂BIPC_INFO, MSG_INFO, IPC_STAT,
  MSG_STAT, IPC_SET, IPC_RMIDłBbZ[WL[IDƑp[^
  mFA(cmd)ȉ̂悤Ɏs܂B

  5.2.1.2.1.  IPC_INFO (܂ MSG_INFO)

  O[obZ[WL[̏񂪃[UԂɃRs[܂B

  5.2.1.2.2.  IPC_STAT (܂ MSG_STAT)

  ^Cv ``struct msqid64_ds'' ̈ꎞobt@AO[o
  bZ[WL[XsbN擾܂BĂяovZX̃ANZX
  mFAbZ[WL[IDɑΉĂ郁bZ[WL[̏
  Aꎞobt@֓ǂݍ݂܂BăbZ[WL[XsbN
  ܂Bꎞobt@̓éA[UԂ``copy_msqid_to_user()''
  ɂ菑o܂B

  5.2.1.2.3.  IPC_SET

  [Uf[^́A``copy_msqid_to_user()''ɂRs[܂BO[o
  bZ[WL[Z}tHƃXsbN͂̂Ƃ擾AŌɉ
  ܂BbZ[WL[ID ƌ݂̃vZX̃ANZX̗Lm
  FꂽAbZ[WL[̏񂪃[U^ꂽf[^ōXV
  ܂B̌A ``expunge_all()''  ``ss_wakeup()'' ĂяoAS
  ẴbZ[WL[̎󂯎Ƒ̃EGCgL[ŋx~Ăv
  ZXN܂B́ÂƂɂ͎󂯎肪ȃANZXɂr
  ĂA肪L[TCYƂɂ胁bZ[W̑M
  \ɂȂꍇ邽߂łB

  5.2.1.2.4.  IPC_RMID

  O[obZ[WL[Z}tH擾AO[obZ[W
  L[XsbNbN܂BbZ[WL[IDƌ݂̃^XN
  ANZX̗LmFꂽƁA``freeque()''Ăяoăb
  Z[WL[IDɑΉÂĂ郊\[X܂BāAO[
  obZ[WL[Z}tHƃXsbN܂B

  5.2.1.3.  sys_msgsnd()

  sys_msgsng() ́Ap[^ƂăbZ[WL[ID(msqid)A``struct
  msg_msg'' ^Cṽobt@ւ̃|C^(msgp)A郁bZ[W̃TC
  Y(msgsz)ƁA҂ۂtO(msgflg)󂯎܂BbZ[W
  L[IDɑΉ̂́A2̃^XNEGCgL[ƁA1̃bZ[WE
  GCgL[܂B󂯎EGCgL[ɂ̃bZ[W҂Ă
  ^XN΁AbZ[W͒ڎ󂯎֓͂A󂯎͋N
  BłȂ΁AbZ[WEGCgL[ɏ\ȗ]T΁Ab
  Z[W͂̃L[֊i[܂Bǂ́Ã^XN͎g𑗂
  EGCgL[ւ܂Bsys_msgsnd()鑀̂ڍׂȓe
  ̂悤ɂȂ܂B

  1. [Uobt@AhXƃbZ[W^Cv̗LmFǍ
     ``load_msg()'' ĂяoāA[UbZ[W̓eA``struct
     msg_msg''^Cv̈ꎞIuWFNgmsg֓ǂݍ݂܂B msg̃bZ[
     W^CvƃbZ[WTCŸ܂B

  2. O[obZ[WL[XsbNbNāAbZ[W
     L[IDɑΉÂ郁bZ[WL[Lqq擾܂B̂
     ȃbZ[WL[݂Ȃ΁AEINVAL Ԃ܂B

  3. bZ[WL[IDLł邩mF邽߁A(msg_checkid()oR
     )``ipc_checkid()''Ăяo܂BāA``ipcperms()'' Ăяo
     āAďõvZX̃ANZX`FbN܂B

  4. bZ[W̃TCYƃbZ[WEGCgL[̎cTCY`FbN
     āAbZ[Wi[̂ɏ\]T邩ǂׂ܂B
     s\ł΁Aȉ̕ڂ{܂B

     a.  IPC_NOWAIT msgflg Ɏw肳Ă΁AO[obZ[
        WL[XsbNAbZ[Wp̃̈悪
        āAEAGAIN Ԃ܂B

     b. ``ss_add()'' NÃ݂^XN𑗂茳EGCgL[ւƂ
        ܂B͂܂AO[oL[XsbN
        Aschedule() ĂяoāÃ݂^XNx~܂B

     c. NꂽAēxO[oXsbN擾AbZ[W
        L[ID܂LmF܂BbZ[WL[IDLł
        ΁AERMID Ԃ܂B

     d. ``ss_del()'' NA茳EGCgL[瑗̃^XN
        폜܂B^XNɕۗꂽVOi΁A
        sys_msgsnd() ̓O[oXsbNA ``free_msg()''
        NāAbZ[Wobt@EINTR Ԃ܂B
        Ȃ΁A֐ ``߂''AbZ[WEGCgL[ɏ\ȗ]T
        邩ēx`FbN܂B

  5. ``pipelined_send()'' NāAbZ[W҂Ă󂯎ɒ
     ܂B

  6. ̃bZ[W҂󂯎肪Ȃ΁Amsg bZ[WEGCg
     L[(msg->q_messages) ֊i[܂B

     ϐmsg_bytes  msg_hdrs ̓bZ[WɎg鑍oCg
     VXeŜ̃bZ[WӖĂ܂A ƓlAb
     Z[WL[Lqq q_cbytes  q_qnum ̈XV܂BbZ[
     W̑MAL[ɂꂽꍇ́AbZ[WL[L
     qqq_lspidq_stime ̈XVAO[obZ[WXsb
     N܂B
  5.2.1.4.  sys_msgrcv()

  sys_msgrcv() ֐́Ap[^ƂăbZ[W
  L[ID(msqid)A``msg_msg'' ^̃obt@ւ̃|C^(msgp)A]
  bZ[W̃TCY(msgsz)ƃtO(msgflg)󂯎܂BbZ[W
  L[IDɊ֘A郁bZ[WEGCgL[Av^Ƀ}b`
  L[̍ŏ̃bZ[WA^ꂽ[Uobt@փRs[
  ܂BÂ悤ȃbZ[WAbZ[WEGCgL[Ɍ
  ȂAṽ^XN͊]郁bZ[W܂Ŏ󂯎EGC
  gL[֓܂Bss_msgrcv() ɂ鑀́AڍׂȐ͈ȉ
  ̒ʂłB

  1. ܂Amsgtyp猟[hh``convert_mode()''N
     B sys_msgrcv() ̓O[obZ[WL[XsbN
     bNBăbZ[WL[ID ɑΉ郁bZ[WL[Lq
     q𓾂BbZ[WL[Ȃ EINVAL ԂB

  2. ݂̃^XNbZ[WL[ANZXp[~bV
     邩ǂ`FbN܂B

  3. bZ[WEGCgL[̍ŏ̃bZ[W珇 ``testmsg()'' 
     ĂяoÃbZ[W^Cvvꂽ^Cvƈv邩mF
     B sys_msgrcv() ́AK郁bZ[W邩ASẴEGC
     gL[Ts܂ŌpB[h
     SEARCH_LESSEQUAL ł΁Amsgtyp ȉōł^CṽL[
     ŏ̃bZ[WTB

  4. bZ[WA sys_msgrcv() ͈ȉ̃TuXebv
     sB

     a. bZ[WTCYz肳ꂽTCY傫Amsgflg G
        [eȂĂAO[obZ[WL[Xsb
        NAE2BIG ԂB

     b. bZ[WEGCgL[烁bZ[W폜AbZ[WL[
        ̓vXVB

     c. EGCgL[ŋx~ĂSẴ^XNNBÕX
        ebvŃL[烁bZ[W폜ƂŁA̒ɂ͏
        pł̂邩炾BāA``Ō̃Xebv''ւƐi
        ށB

  5. bZ[WEGCgL[Ɏ󂯎̊ɍv郁bZ[W
     ȂAmsgflgmFB IPC_NOWAIT ݒ肳
     AO[obZ[WL[XsbNAENOMSG 
     BłȂ΁A󂯎͈ȉ̂悤Ɏ󂯎EGCgL[֓
     B

     a. ``msg_receiver'' f[^\̂ msr 蓖āAEGCgL[
        擪ɒǉB

     b. msr  r_tsk oɌ݂̃^XNݒ肷B

     c. r_msgtype  r_mode o͏AbZ[W̃^Cvƃ[
        hꂼvꂽlɂB

     d.  msgflg  MSG_NOERROR ƂȂĂA msr  r_maxsize 
        o msgsz ̒lݒ肳BłȂ INT_MAX ݒ肳
        B

     e. o r_msg ̓bZ[W܂󂯎ĂȂԂ\悤
        B
     f. ̊A󂯎̃^XN̏Ԃ TASK_INTERRUPTIBLE ɐݒ
        BăO[obZ[WL[XsbN͉A
        schedule() ĂяoB

  6. 󂯎肪NƁAmsr  r_msg o `FbNB̃
     o̓pCvC̃bZ[W̊i[ɎgAG[̏ꍇɂ̓G[
     Ԃi[BAr_msg ovꂽbZ[Wł
     ɂȂA``Ō̃Xebv'' ֐iށBȊȌꍇ́AO[o
     bZ[WL[XsbNēxbNB

  7. XsbN̎擾Ar_msg óAXsbN҂ĂԂ
     bZ[W󂯎ĂȂAēxmFBbZ[W
     󂯎ĂȂA``Ō̃Xebv'' ֐iށB

  8. Ar_msg oύXĂȂȂAĎŝ߃^XNN
     B̏ꍇAmsr ̓L[폜B^XNɕۗ
     VOi΁AO[obZ[WL[XsbN͉
     A EINTR ԂBȊOł́A֐``߂'' AĎs
     B

  9. r_msgoɂAx~ɃG[Ƃ΁AO
     [obZ[WL[XsbN͉AG[ԂB

  10.

     [Uobt@̃AhXmsp̗LmFƁAbZ[W^Cv
     msp  mtypeoɏ܂A ``store_msg()'' ĂяoāA
     bZ[W̓emsrmtextoփRs[܂BŌɃbZ[
     Wp̃֐ ``free_msg()''ɂ܂B

  5.2.2.  bZ[WƎ̍\

  bZ[WL[̃f[^\̂ msg.c Œ`Ă܂B

  5.2.2.1.  struct msg_queue

       ______________________________________________________________________
       /* one msq_queue structure for each present queue on the system */
       struct msg_queue {
               struct kern_ipc_perm q_perm;
               time_t q_stime;                 /* last msgsnd time */
               time_t q_rtime;                 /* last msgrcv time */
               time_t q_ctime;                 /* last change time */
               unsigned long q_cbytes;         /* current number of bytes on queue */
               unsigned long q_qnum;           /* number of messages in queue */
               unsigned long q_qbytes;         /* max number of bytes on queue */
               pid_t q_lspid;                  /* pid of last msgsnd */
               pid_t q_lrpid;                  /* last receive pid */

               struct list_head q_messages;
               struct list_head q_receivers;
               struct list_head q_senders;
       };
       ______________________________________________________________________

  5.2.2.2.  struct msg_msg

  ______________________________________________________________________
  /* one msg_msg structure for each message */
  struct msg_msg {
          struct list_head m_list;
          long  m_type;
          int m_ts;           /* message text size */
          struct msg_msgseg* next;
          /* the actual message follows immediately */
  };
  ______________________________________________________________________

  5.2.2.3.  struct msg_msgseg

       ______________________________________________________________________
       /* message segment for each message */
       struct msg_msgseg {
               struct msg_msgseg* next;
               /* the next part of the message follows immediately */
       };
       ______________________________________________________________________

  5.2.2.4.  struct msg_sender

       ______________________________________________________________________
       /* one msg_sender for each sleeping sender */
       struct msg_sender {
               struct list_head list;
               struct task_struct* tsk;
       };
       ______________________________________________________________________

  5.2.2.5.  struct msg_receiver

       ______________________________________________________________________
       /* one msg_receiver structure for each sleeping receiver */
       struct msg_receiver {
               struct list_head r_list;
               struct task_struct* r_tsk;

               int r_mode;
               long r_msgtype;
               long r_maxsize;

               struct msg_msg* volatile r_msg;
       };
       ______________________________________________________________________

  5.2.2.6.  struct msqid64_ds

       ______________________________________________________________________
       struct msqid64_ds {
               struct ipc64_perm msg_perm;
               __kernel_time_t msg_stime;      /* last msgsnd time */
               unsigned long   __unused1;
               __kernel_time_t msg_rtime;      /* last msgrcv time */
               unsigned long   __unused2;
               __kernel_time_t msg_ctime;      /* last change time */
               unsigned long   __unused3;
               unsigned long  msg_cbytes;      /* current number of bytes on queue */
               unsigned long  msg_qnum;        /* number of messages in queue */
               unsigned long  msg_qbytes;      /* max number of bytes on queue */
               __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
               __kernel_pid_t msg_lrpid;       /* last receive pid */
               unsigned long  __unused4;
               unsigned long  __unused5;
       };
       ______________________________________________________________________

  5.2.2.7.  struct msqid_ds

       ______________________________________________________________________
        struct msqid_ds {
               struct ipc_perm msg_perm;
               struct msg *msg_first;          /* first message on queue,unused  */
               struct msg *msg_last;           /* last message in queue,unused */
               __kernel_time_t msg_stime;      /* last msgsnd time */
               __kernel_time_t msg_rtime;      /* last msgrcv time */
               __kernel_time_t msg_ctime;      /* last change time */
               unsigned long  msg_lcbytes;     /* Reuse junk fields for 32 bit */
               unsigned long  msg_lqbytes;     /* ditto */
               unsigned short msg_cbytes;      /* current number of bytes on queue */
               unsigned short msg_qnum;        /* number of messages in queue */
               unsigned short msg_qbytes;      /* max number of bytes on queue */
               __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
               __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
       };
       ______________________________________________________________________

  5.2.2.8.  msg_setbuf

       ______________________________________________________________________
       struct msq_setbuf {
               unsigned long   qbytes;
               uid_t           uid;
               gid_t           gid;
               mode_t          mode;
       };
       ______________________________________________________________________

  5.2.3.  bZ[WT|[g֐

  5.2.3.1.  newque()

  newque() ́AVbZ[WL[Lqq(``struct msg_queue'')̂
  ̃蓖āA``ipc_addid()'' ĂяoāAVbZ[W
  L[LqqpɃbZ[WL[z̃Gg\񂳂܂BbZ[
  WL[Lqq͈ȉ̂悤ɏ܂B

  o  ``kern_ipc_perm''\̂B

  o  bZ[WL[Lqqq_stimeq_rtimeo 0 ɏ
     Bq_ctimeo CURRENT_TIME ɐݒ肳B

  o  ̃L[bZ[WŋőoCg(q_qbytes) MSGMNB ɐ
     肳AL[ɂ茻ݎgĂoCg(q_cbytes)0ɏ
     B

  o  bZ[WEGCgL[(q_messages)A҂EGCg
     L[(q_receivers)AEGCgL[(q_senders)ꂼ
     B

     ``ipc_addid()'' ̌ďoɂÂSĂ̑́AO[obZ[W
     L[XsbNێĎs܂BXsbN
     Anewque() ́A  ``ipc_buildid()'' ɒڃ}bvĂ
     msg_buildid() Ăяo܂B``ipc_buildid()'' ́AbZ[W
     L[Lqq̃CfbNXpăj[NȃbZ[WL[ ID 
     肾܂BẮA newque() ɂďoɖ߂܂B

  5.2.3.2.  freeque()

  bZ[WL[폜Ƃ́A freeque() ֐Ă΂܂B
  ֐́AO[obZ[WL[XsbNAďo֐ɂ
  ɃbNĂ̂Ɖ肵܂Bw肳郁bZ[WL[Ɋ֘A
  ĂSẴJ[l\[X܂B܂A(msg_rmidoR
  )``ipc_rmid()'' ĂяoAO[obZ[WL[Lqq̔z
  烁bZ[WL[Lqq폜܂BāA``expunge_all'' Ăяo
  āASĂ̎󂯎NA``ss_wakeup()''ĂяoāÃbZ[
  WL[ŋx~ĂSĂ̑N܂BŌɁAO[ob
  Z[WL[XsbN܂B̃bZ[WL[Ɋi[
  SẴbZ[W͉AbZ[WL[Lqq̃
  ܂B

  5.2.3.3.  ss_wakeup()

  ss_wakeup() ͗^ꂽbZ[WEGCgL[ő҂ɂȂĂ
  SẴ^XNN܂B̊֐``freeque()''Ă΂ꂽȂA
  L[ɂSĂ̑̓L[폜܂B

  5.2.3.4.  ss_add()

  ss_add() ̓p[^ƂăbZ[WL[LqqƃbZ[W
  f[^\̂󂯎܂B݂̃vZXƂɃbZ[Wf[
  ^\̂tsk o𖄂߁Ã݂vZX̏Ԃ TASK_INTERRUPTIBLE
  ɕύXAė^ꂽbZ[WL[̑EGCgL[̐擪
  փbZ[Wf[^\̂}܂B

  5.2.3.5.  ss_del()

  ^ꂽbZ[Wf[^\(mss) ͂܂ΉEGCg
  L[ɕۊǂꂽ܂܂łBāAss_del() ́AmssL[폜
  ܂B

  5.2.3.6.  expunge_all()

  expunge_all() ́Ap[^ƂăbZ[WL[Lqq(msq)Ǝ󂯎
  NꂽRl(res)󂯎܂BꂼmsqɑΉ
  ċx~̎󂯎ɑ΂āAr_msg oNꂽR(res)ݒ肵A
  ̑Ή󂯎̃^XNN܂B̊֐̓bZ[WL[
  폜ƂƁAbZ[W䑀삪sƂɌĂяo܂B

  5.2.3.7.  load_msg()

  vZXbZ[W𑗂ƂA``sys_msgsnd()'' ֐́Aŏ
  load_msg() ֐ĂяoAbZ[W[UԂJ[lԂւ
  ǂݍ݂܂BbZ[W̓J[lł̓f[^ubÑN
  XgƂĕ\Ă܂Bŏ̃f[^ubNɊ֘AĂ̂́AS
  ẴbZ[W\``msg_msg'' \̂łBmsg_msg \̂Ɋ֘AÂ
  Ăf[^ubŃADATA_MSG_LEN ̃TCYɐĂ܂B
  f[^ubNƍ\̂̓ňy[WŎ肤ő̈̘A
  ubNɊ蓖ĂĂ܂BSẴbZ[Wŏ̃f[
  ^ubNɓ肫Ȃ΁Aǉ̃f[^ubN蓖ĂA
  NXgɓo^܂Bǉ̃f[^ubŃADATA_SEG_LEN 
  TCYĂAeX͊֘A``msg_msgseg)'' \̂ǂݍ
  ܂Bmsg_msgseg \̂ƑΉf[^ubN̓ňy[WŎ
  肤ő̈̘AubNɊ蓖ĂĂ܂B̊
  ́Aɂ͐V``msg_msg'' \̂̃AhXԂlɂĖ߂
  ܂B

  5.2.3.8.  store_msg()

  store_msg() ֐́A``sys_msgrcv()'' ɂĂяoA󂯂bZ[
  Wďo̒񋟂郆[Uԃobt@֍ēxgݗĂ܂B
  ``msg_msg'' \̂``msg_msgseg''\̂ɂ莦f[^́A[U
  ԃobt@֏Rs[܂B

  5.2.3.9.  free_msg()

  free_msg() ֐̓bZ[Wf[^\ ``msg_msg'' ƃbZ[WZO
  g̃܂B

  5.2.3.10.  convert_mode()

  convert_mode()  ``sys_msgrcv()'' Ăяo܂Bp[^Ƃ
  āAw肷郁bZ[W^Cṽ|C^(msgtyp)ƃtO(msgflg)󂯎
  ܂B̊֐́Amsgtypmsgflg̒lɊÂāAďo֌[h
  Ԃ܂BAmsgtyp0Ȃ΁A SEARCH_ANYԂ܂BAmsgtyp
  ̒l0菬΁Amsgtype͂̐Βlɐݒ肳ASEARCH_LESSEQUAL
  Ԃ܂B MSG_EXCEPT msgflg Ɏw肳Ă
  ΁ASEARCH_NOTEQUAL Ԃ܂BłȂ΁ASEARCH_EQUAL Ԃ
  ܂B

  5.2.3.11.  testmsg()

  testmsg() ֐́AbZ[W󂯎̎w肷ɍv邩ׂ
  BAȉ̏̈^ƂȂ΁A1Ԃ܂B

  o  [hSbZ[W(SEARCH_ANY)̏ꍇ

  o  [h SEARCH_LESSEQUAL Ɏw肳ĂAbZ[W^Cv
     w肳ꂽ^Cvȉłꍇ

  o  [h SEARCH_EQUAL ŃbZ[W^Cvw肳ꂽ^CvƓ
     łꍇ

  o  [h SEARCH_NOTEQUAL ŁAbZ[W^Cvw肳ꂽ^Cv
     ƈقȂꍇ
  5.2.3.12.  pipelined_send()

  vZX pipelined_send() gƂŁAΉÂĂ郁bZ[W
  L[֓̂ł͂ȂAڑҋ@̎󂯎փbZ[W𑗂邱Ƃ
  ܂B^ꂽbZ[W҂ŏ̎󂯎邽߁A
  ``testmsg()'' ֐Ăяo܂B΁A҂Ă󂯎͎
  EGCgL[폜A֘A󂯎̃^XN͋N܂B
  bZ[W͎󂯎r_msgo֊i[āA1Ԃ܂BbZ[W
  ҂Ă󂯎肪ȂꍇA0Ԃ܂B

  󂯎TvZXł́A^ꂽbZ[Wɑ΂ďTCY
  vĂ邱ƂŁAݓI󂯎肪ł傤B̂悤Ȏ󂯎
  L[폜ANăG[ E2BIG n܂B̃G
  [́Ar_msgoɊi[܂B̌́ALȎ󂯎肪
  AL[s܂Ōp܂B

  5.2.3.13.  copy_msqid_to_user()

  copy_msqid_to_user() ̓J[lobt@̓e[Uobt@ɃRs[
  ܂Bp[^Ƃă[Uobt@ ``msqid64_ds'' ^̃J[l
  obt@ƁAVIPC o[WÂ IPC o[Wo[W
  tO󂯎܂Bo[WtO IPC_64 Ȃ΁A
  copy_to_user() NAJ[lobt@烆[Uobt@֒ڃR
  s[܂BłȂ΁Astruct msqid_ds ^̈ꎞobt@
  AJ[lf[^͂̈ꎞobt@֕ϊ܂B
  āAcopy_to_user() ĂяoAꎞobt@̓e[Uobt@
  Rs[܂B

  5.2.3.14.  copy_msqid_from_user()

  copy_msqid_from_user() ֐́Ap[^Ƃstruct msq_setbuf^
  J[lbZ[Wobt@ƃ[Uobt@ƁAVIPC o[W
   IPC o[Wo[WtO󂯎܂BIPCo[W
  VꍇAcopy_from_user()ĂяoāA[Uobt@̓e
  ``msqid64_ds'' ^̈ꎞobt@փRs[܂BăJ[lobt@
  qbytes, uid, gidmodëꎞobt@̑Ή̈̒lɂ܂B
  Â IPC ̃o[WȂ΁A``msqid_ds'' ^̈ꎞobt@ɗp
  ܂B

  5.3.  L

  5.3.1.  LVXeR[C^[tF[X

  5.3.1.1.  sys_shmget()

  sys_shmget() ́AďoŜO[oLZ}tHɂی삵
  ܂B

  VLZOgKv̂ꍇA ֐``newseg()'' 
  яoAVLZOg쐬܂BVZO
  gIDďo֕Ԃ܂B

  ̋LZOg L[l^ĂꍇALL
  qqz̑ΉCfbNXoAp[^ƌďõp[
  ~bVmFALZOgIDԂ܂BƗL
  ̊mF̓O[oLXsbNێԂōs܂B

  5.3.1.2.  sys_shmctl()

  5.3.1.2.1.  IPC_INFO

  ꎞobt@ ``shminfo64'' VXeCh̋Lp[^Ƃ
  ɓǂݍ܂AďõAvP[VANZX郆[UԂ
  Rs[܂B

  5.3.1.2.2.  SHM_INFO

  L̃VXeCh̓vW߂Ԃ́AO[oL
  Z}tHƃO[oLXsbN擾܂B
  ``shm_get_stat()'' ĂяoAɑ݂鋤Ly[W
  ƃXbvAEgLy[WvZ܂B swap_attempts
  swap_successešv́A0 ƂĂ܂B̓vl͈ꎞ
  obt@ ``shm_info'' ֊i[AĂяoAvP[Ṽ[U
  ԂւƃRs[܂B

  5.3.1.2.3.  SHM_STAT, IPC_STAT

  SHM_STAT  IPC_STAT ̂߁A``struct shmid64_ds'' ^̈ꎞobt@
  AO[oLXsbNbN܂B

  SHM_STAT ̏ꍇ́ALZOg ID p[^́AP̃C
  fbNX(܂A0  n ŁAn ̓VXe̋L ID ̔ԍ) 
  ҂Ă܂BCfbNX̗LmFA``ipc_buildid()''
  (shm_buildid()oR)ĂяoACfbNXL ID ֕ϊ
  ܂BSHM_STAT nꍇAL ID ԂlɂȂ܂B
  @\͕ɂȂǂAipcs(8) vÔ߂ɏĂ邱
  ɒӂ܂傤B

  IPC_STAT ̏ꍇALZOg ID p[^ɂāAID
  ``shmget()'' ďoĐĂ邱Ƃ҂܂B ID ͏
  sOɗLmF܂BIPC_STAT nꍇA0 Ԃl
  Ȃ܂B

  SHM_STAT IPC_STAT ̑oɂāAďõANZX̗LmF
  ܂Bvꂽv͈ꎞobt@֓ǂݍ܂Ǎďo
  Rs[܂B

  5.3.1.2.4.  SHM_LOCK, SHM_UNLOCK

  ANZX̗LmFAO[oLXsbNbN
  ALZOgID̗LmF܂BSHM_LOCK  SHM_UNLOCK
  oŁȀs߁A``shmem_lock()'' Ăяo
  B``shmem_lock()''̃p[^ɂ́Aׂ֐̎ʎqn
  B

  5.3.1.2.5.  IPC_RMID

  IPC_RMID ̏̊Ԃ́AO[oLZ}tHƃO[oL
  XsbN擾܂BLID ̗LmFƁA
   current attachment Ȃ΁A``shm_destroy()'' ďoAL
  ZOgj󂵂܂BłȂ΁ASHM_DEST tOZbg
  Aꂪj󂷂ƂɂȂ܂BāÃvZXL
  ID̎QƂ邽߂ɁAIPC_PRIVATE tOZbg܂B

  5.3.1.2.6.  IPC_SET

  LZOgIDƃ[ŨANZX̗LmFAL
  ZOguidgidAmode tO[Uf[^ōXV
  Bshm_ctimëXV܂B̕ύX́AO[oLZ
  }tHƃO[oLXsbNێԂŏ܂B

  5.3.1.3.  sys_shmat()

  sys_shmat() ́ALZOgIDƋLZOgzu
  AhX(shmaddr)AĈȉɎtOp[^Ɏ܂B

  shmaddr0łȂASHM_RND tOw肳ĂȂAshmaddr
  SHMLBA ̔{ւƊۂ߂܂BAshmaddr SHMLBA̔{ł
  ASHM_RND w肳ĂȂ΁AEINVAL Ԃ܂B

  ďõANZX̗LmFALZOg
  shm_nattcḧ悪1܂BŁȂ 蓖ăJEg
  0ł͂ȂƂۏ؂ALZOgZOg̊蓖ď
  ̔j󂩂邽߂ɍs܂B̑́AO[oL
  XsbNێԂōs܂B

  LZOgy[Wւ̉z}bv邽߁A do_mmap()
  ֐Ăяo܂B̓Jg^XN mmap_sem Z}tHێ
  Ԃōs܂BMAP_SHARED tO do_mmap() ֓n܂BAh
  XďonꂽȂA MAP_FIXED tO do_mmap() ֓n
  ܂BłȂ΁A LZOg֊蓖Ă鉼zAhX
  do_mmap() Iт܂B

  : ``shm_inc()'' do_mmap() ֐R[̒ shm_file_operations \
  ̂oċN܂B̊֐́A PID ݒ肵A݂̎ݒ
  A̋LZOgւ̊蓖Đ𑝕邽ߌĂяo
  B

  do_mmap() ĂяoƂ́AO[oLZ}tHƃO[o
  LXsbN̗擾܂B蓖ăJEg͌
  ܂B

  ``shm_inc()'' Ăяo߁Ashmat()ւ̌Ăяoɑ΂Ċ蓖Đ
  ̕ύX 1 ɂȂ܂B蓖Đ̌ŁAZOg
  jɃ}[N(SHM_DEST)ꂽA``shm_destroy()'' ĂяoAL
  ZOg̎܂B`

  ŌɁAL̃}bv鉼zAďõ[U̎w肵
  AhX֕Ԃ܂B do_mmap() G[R[hԂꂽƂ
  ́ÃG[R[hVXeR[̕ԂlƂĖ߂܂B

  5.3.1.4.  sys_shmdt()

  sys_shmdt() ̏̓O[oLZ}tHێ܂B
  ̃vZXmm_struct ɂāALAhXɑΉ
  vm_area_struct ܂B΁A do_munmap() Ăяo
  āALZOg̉zAhXւ̃}bsO܂B

  ŁA do_munmap() ͋L̗\ێ֐``shm_close()''
  R[obNÅ蓖ĂȂLZOg̎
  邱ƂɒӂĂB

  sys_shmdt() ͖0Ԃ܂B

  5.3.2.  LT|[g\

  5.3.2.1.  struct shminfo64

  ______________________________________________________________________
  struct shminfo64 {
          unsigned long   shmmax;
          unsigned long   shmmin;
          unsigned long   shmmni;
          unsigned long   shmseg;
          unsigned long   shmall;
          unsigned long   __unused1;
          unsigned long   __unused2;
          unsigned long   __unused3;
          unsigned long   __unused4;
  };
  ______________________________________________________________________

  5.3.2.2.  struct shm_info

       ______________________________________________________________________
       struct shm_info {
               int used_ids;
               unsigned long shm_tot;  /* total allocated shm */
               unsigned long shm_rss;  /* total resident shm */
               unsigned long shm_swp;  /* total swapped shm */
               unsigned long swap_attempts;
               unsigned long swap_successes;
       };
       ______________________________________________________________________

  5.3.2.3.  struct shmid_kernel

       ______________________________________________________________________
       struct shmid_kernel /* private to the kernel */
       {
               struct kern_ipc_perm    shm_perm;
               struct file *           shm_file;
               int                     id;
               unsigned long           shm_nattch;
               unsigned long           shm_segsz;
               time_t                  shm_atim;
               time_t                  shm_dtim;
               time_t                  shm_ctim;
               pid_t                   shm_cprid;
               pid_t                   shm_lprid;
       };
       ______________________________________________________________________

  5.3.2.4.  struct shmid64_ds

  ______________________________________________________________________
  struct shmid64_ds {
          struct ipc64_perm       shm_perm;       /* operation perms */
          size_t                  shm_segsz;      /* size of segment (bytes) */
          __kernel_time_t         shm_atime;      /* last attach time */
          unsigned long           __unused1;
          __kernel_time_t         shm_dtime;      /* last detach time */
          unsigned long           __unused2;
          __kernel_time_t         shm_ctime;      /* last change time */
          unsigned long           __unused3;
          __kernel_pid_t          shm_cpid;       /* pid of creator */
          __kernel_pid_t          shm_lpid;       /* pid of last operator */
          unsigned long           shm_nattch;     /* no. of current attaches */
          unsigned long           __unused4;
          unsigned long           __unused5;
  };
  ______________________________________________________________________

  5.3.2.5.  struct shmem_inode_info

       ______________________________________________________________________
       struct shmem_inode_info {
               spinlock_t      lock;
               unsigned long   max_index;
               swp_entry_t     i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */
               swp_entry_t   **i_indirect; /* doubly indirect blocks */
               unsigned long   swapped;
               int             locked;     /* into memory */
               struct list_head        list;
       };
       ______________________________________________________________________

  5.3.3.  LT|[g֐

  5.3.3.1.  newseg()

  newseg() ֐́AVLZOgKvoƂɌĂ
  ܂B́AVZOg̃L[AtOATCY̎O̃p[
  ^󂯎܂B쐬鋤LZOg̃TCY SHMMIN 
  SHMMAX ̊ԂɂALZOg̑ SHMALL zȂ
  LmFɁAVLZOgLqq蓖
  ܂B ``shmem_file_setup()'' ֐́Atmpfs ^̃ANꂽt@C
  쐬邽߂ɁǍɌĂяo܂BԂt@C|C^
  ́ALZOgLqq̑Ήshm_filë֕ۑ܂B
  t@CTCY̓ZOgTCYƓɐݒ肳܂BVL
  ZOgLqq͏AO[o IPC LLqqz֑}
  ܂BLZOg ID  (``ipc_buildid()''oR)
  shm_buildid() ɂ쐬܂B̃ZOgID́Ainode ɑΉ
  i_ino ̈ƓlɋLZOgLqq id ̈֕ۑ܂B
  ɉāAshm_file_operation\̂Œ`鋤L̃Ah
  X́AΉt@Cւƕۑ܂BVXeŜł̋LZ
  Og̑O[oϐ shm_tot ̒lA̕ύX𔽉f
  ܂BꍇAZOg ID ďoAvP[V
  Ԃ܂B

  5.3.3.2.  shm_get_stat()

  shm_get_stat() ́ASĂ̋L\̂ɒHĂAL
  ɎgĂ郁̑Sy[WƁAXbvAEgĂS
  y[WvZ܂BeLZOgɂ̓t@C\̂im[
  h\̂܂B߂f[^im[hoRŎ擾邽߁AANZX
  eim[h\̂̃XsbÑbNƃbNAꂼ
  s܂B

  5.3.3.3.  shmem_lock()

  shmem_lock() ̓p[^ɋLLqqւ̃|C^ƃbNA
  bNtO󂯎܂BLZOg̃bNԂ͑
  im[h֊i[܂B̏Ԃ́AvꂽbNԂƔr
  ܂Bshmem_lock() ́AvꍇɒPɕԂ܂B

  Ήim[h̃Z}tHێĂԂɁAim[h̃bNԂݒ
  ܂BeLZOg̊ey[WɂāAȉ̃Xg̍
  s܂B

  o  find_lock_page() ́Ay[WbN(PG_lockedݒ)Ay[W̎Q
     ƃJE^1܂BQƃJE^̉Z͋LZOg
     ̑쒆ʂẵbNꂽԂɂ邱Ƃۏ؂邽
     ߂Ɏ{܂B

  o  vꂽԂbNԂȂ PG_locked ̓NA܂AQ
     ƃJE^͑ꂽ܂܂ɂ܂B

  o  vꂽԂAbNԂȂAQƃJE^2xZ
     B݂͌̎QƁA̓̒ŃbNꂽ܂܂̃y[
     WɂȂ錴̊̎QƂ̂߂łBꂩ PG_locked ̓NA
     ܂B

  5.3.3.4.  shm_destroy()

  shm_destroy() ̊ԁALy[ẂALZOg̍폜
  ̐ӔCƂĒ܂B ``ipc_rmid()'' ́A(shm_rmid() oR)
  яoALID 폜܂B ``shmem_lock'' ĂяoA
  Ly[WAbNAey[W̎QƃJEgI 0 Ɍ
  Z܂B fput() ĂяoAΉt@CIuWFNg̗pJE
  ^f_count1Z܂BāAKvł΁At@CIuWFNg
  ܂Bkfree() ĂяoALZOgLqq
  ܂B

  5.3.3.5.  shm_inc()

  shm_inc()  PID ݒ肵A݂̎Ԃݒ肵Aė^ꂽL
  ZOg̕t1܂B̑́AO[oL
  XsbNێčs܂B

  5.3.3.6.  shm_close()

  shm_close() ́Ashm_lprid  shm_dtim oXVA蓖ċL
  ZOg 1 Z܂BLZOgɊ蓖Ă
  ĂȂ΁A``shm_destroy()'' ĂяoALZOg̎
  ܂B̑͑SăO[oLZ}tHƃO[o
  LXsbN̗ێčs܂B

  5.3.3.7.  shmem_file_setup()

  ֐ shmem_file_setup() ́A tmpfs t@CVXeɑ݂A
  Nꂽt@CA^ꂽOƃTCYɐݒ肵܂B̃t@C
  ɑ΂ď\ȃVXe\[X΁AV dGg
  tmpfs ̃}Eg[gɍ쐬܂BĐVt@CfBXNv^
   tmpfs ^̐V im[hIuWFNg蓖Ă܂B
  āAd_instantiate() ďoAV d GgIuWFNgɐV i
  m[hIuWFNgΉÂ܂BdGgIuWFNg̃AhX
  t@CfBXNv^֕ۑ܂Bim[hIuWFNgi_size o
  ̓t@CTCYɐݒ肳Aim[hANꂽ邽
  i_nlink  0 ɐݒ肵܂BāA shmem_file_setup()
  ́Ashmem_file_operations \̂̃AhX f_op o֕ۑ܂B
  āAt@CfBXNv^ f_mode  f_vfsmnt oK؂ɏ
  ܂B֐ shmem_truncate() ĂяoAim[h IuWFNg
  ܂BȂA shmem_file_setup() ͐Vt@C
  fBXNv^Ԃ܂B

  5.4.  Linux IPC v~eBu

  5.4.1.  Z}tHAbZ[WыLŎgpėp Linux IPCv
  ~eBu

  Linux ̃Z}tHAbZ[WыL@\͈A̋ʃv~eB
  uō\Ă܂B̃v~eBuȉŐ܂B

  5.4.1.1.  ipc_alloc()

  蓖Ă PAGE_SIZE 傫΁Avmalloc() 蓖
  Ɏg܂BłȂ΁A kmalloc()  GFP_KERNEL tŌĂяo
  ꃁ蓖Ă܂B

  5.4.1.2.  ipc_addid()

  VZ}tHZbgAbZ[WL[AȂ̓ZOgǉ
  ƁA ipc_addid() ́A֘AfBXNv^̔z̃TCYVX
  e̍őlɑ΂ď\ɑ傫Ƃۏ؂邽߁Aŏ
  ``grow_ary()'' Ăяo܂BăfBXNv^̔z̍ŏ̖g
  pvf܂Bgp̗vfAgp̃fBXN
  v^̃JE^1܂BṼfBXNv^̂߂
  ``kern_ipc_perm'' \̂AVfBXNv^̔z̃C
  fbNXԂ܂B ipc_addid() A^ꂽIPC ̃^Cv
  ̃O[oXsbN擾Ė߂܂B

  5.4.1.3.  ipc_rmid()

  ipc_rmid() ́AIPCfBXNv^IPC^CṽO[ofBXNv^
  z񂩂폜A gpĂ ID ̃JEgXV܂BĕKv
  ȂΉfBXNv^z̍ő ID 𒲐܂B^ꂽ IPC
  ID ɑΉ IPC fBXNv^ւ̃|C^Ԃ܂B

  5.4.1.4.  ipc_buildid()

  ipc_buildid() ͗^ꂽIPC^Cv̊efBXNv^ɑΉ郆j[
  NID쐬܂B ID ͐VIPCvfǉƂɍ쐬
  ܂(: VLZOgVZ}tHZbg)B IPC ID 
  ΉfBXNv^z̃CfbNX֗eՂɕϊł܂BeIPC^
  Cv́AfBXNv^ǉ閈ɑV[PXԍǗ
  Ă܂B ID ̓V[PXԍSEQ_MULTIPLIER {A̐ςɃfBXN
  v^z̃CfbNXZ邱ƂŐ܂BV[PXԍ
  ݂邱ƂɂAÂ IPC ID ̗po邱Ƃł܂B

  5.4.1.5.  ipc_checkid()

  ipc_checkid() ́A^ꂽ IPC ID SEQ_MULTIPLIER ŏZȀ
  ΉfBXNv^ɕۑĂV[PXlƔr܂B
  lȂAIPC ID ͗LłƍlA1Ԃ܂BłȂ
  ΁A0 Ԃ܂B

  5.4.1.6.  grow_ary()

  grow_ary() ́A^ꂽ IPC ^Cv ő(ݒ\) ID 𓮓I
  ɕύXł@\舵܂B݂͌̍őxPvIȃVXe
  ̌x(IPCMNI)zȂ悤ɋAKvȂ܂B͂܂
  ̃fBXNv^z񂪏\ɑ傫Ȃ悤ۏ؂܂B̔z
  TCY\ɑ傫A݂̍őxԂ܂BłȂ
  ΁AV傫Ȕz蓖Ă܂BČÂzVzփRs[
  AÂz܂B^ꂽ IPC ^CṽfBXNv^z
  XVƂ́AΉO[oXsbNێ܂B

  5.4.1.7.  ipc_findkey()

  ipc_findkey() ́A ``ipc_ids'' IuWFNg̃fBXNv^̔z
  ē̃L[T܂BAΉfBXNv^
  ̃CfbNXԂ܂BL[ȂA-1 Ԃ
  B

  5.4.1.8.  ipcperms()

  ipcperms() ́AIPC ɃANZX郆[UAO[vƑ̃p[~b
  V`FbN܂Bp[~bVLȂ0ԂAł
  -1Ԃ܂B

  5.4.1.9.  ipc_lock()

  ipc_lock() ́A IPC IDp[^̈ƂĎ󂯎܂B^ꂽ
  IPC ^CṽO[oXsbNbNAIPC IDɑΉ
  fBXNv^ւ̃|C^Ԃ܂B

  5.4.1.10.  ipc_unlock()

  ipc_unlock() ́Aꂽ IPC ^CṽO[oXsbN
  B

  5.4.1.11.  ipc_lockall()

  ipc_lockall() ́A^ꂽIPC@\(܂苤LƃZ}tHƃb
  Z[WO)p̃O[oXsbNbN܂B

  5.4.1.12.  ipc_unlockall()

  ipc_unlockall() ́A^ꂽIPC@\(܂苤LƃZ}tHƃb
  Z[WO)p̃O[oXsbN܂B

  5.4.1.13.  ipc_get()

  ipc_get() ́A IPC ^Cv(܂苤LƃZ}tHƃbZ[W
  O)ւ̃|C^ƃfBXNv^IDAΉ IPC fBXNv^
  ւ̃|C^Ԃ܂BŁAe IPC ^CṽfBXNv^Ⴄ
  f[^^CvłĂAꂼ̏ꍇŁAʂ``kern_ipc_perm'' \
  ̃^Cvŏ̃GeBeBƂĖߍ܂܂B ipc_get() ֐́A
  ̋L̃f[^^CvԂ܂Bf[^^𐳂fBXNv^̃f[
  ^^փLXg郉bp[֐(Ƃ shm_get())ʂāAipc_get()
  Ăяo邱Ƃ҂郂fɂȂĂ܂B

  5.4.1.14.  ipc_parse_version()

  ipc_parse_version() ́A IPC_64 tOR}h폜
  BāA IPC_64 IPC_OLDԂ܂B

  5.4.2.  Z}tHAbZ[WыLŎgėp IPC \

  Z}tHAbZ[WыL@\͑SĈȉ̋L̍\̂g
  悤ɂȂĂ܂B

  5.4.2.1.  struct kern_ipc_perm

  e IPC fBXNv^́Aŏ̗vfɂ̌^̃f[^IuWFNg
  Ă܂B́ASĂ̔ėp IPC ֐炱̃f[^^̃|C^p
  āASẴfBXNv^փANZXł悤ɂ邽߂łB

       ______________________________________________________________________
       /* used by in-kernel data structures */
       struct kern_ipc_perm {
           key_t key;
           uid_t uid;
           gid_t gid;
           uid_t cuid;
           gid_t cgid;
           mode_t mode;
           unsigned long seq;
       };
       ______________________________________________________________________

  5.4.2.2.  struct ipc_ids

  ipc_ids \̂́AZ}tHƃbZ[WL[ƋL̋ʃf[^
  \Ă܂B̃f[^\̂ɂ͎O̃O[oCX^X
  BꂼZ}tHAbZ[WALpɁAsemid_dsAmsgid_ds
  shmid_dsłBeCX^Xł́Asem Z}tHgA\̂ւ̃A
  NZXی삵Ă܂B entries óAIPC fBXNv^zw
  ĂAary XsbN̔zւ̃ANZXی삵Ă܂Bseq
  óAV IPC Ƃ1O[oV[PX
  ԍɂȂĂ܂B

       ______________________________________________________________________
       struct ipc_ids {
           int size;
           int in_use;
           int max_id;
           unsigned short seq;
           unsigned short seq_max;
           struct semaphore sem;
           spinlock_t ary;
           struct ipc_id* entries;
       };
       ______________________________________________________________________

  5.4.2.3.  struct ipc_id

  \ ipc_id ̔źA``ipc_ids'' \̂̊eCX^Xɑ݂
  B̔z͓IɊ蓖ĂAKvɉ``grow_ary()''ɂĂ
  傫Ȕzɒu邱ƂɂȂ܂B``kern_ipc_perm'' f[^^
  Cv IPC ėp֐ɂċʃfBXNv^f[^^CvƂĎg
  邽߁A̔z͎XfBXNv^zƂĎQƂ܂B

  ______________________________________________________________________
  struct ipc_id {
      struct kern_ipc_perm* p;
  };
  ______________________________________________________________________

