findの-execでコマンドを起動 #1

findの-execでコマンドを起動するときに、どういうタイミングでfork & execが行われているのだろう。
以下のようにディレクトリとファイルを用意して、

dir
|-- a.txt
|-- b.txt
`-- c.txt

findとgrepを組合せる場合について、ktraceコマンドでトレースをとってみる。

$ ktrace -i /usr/bin/find dir -exec /usr/bin/grep hoge '{}' \;

トレースはktrace.outに出力されるんだけどそのままだと見にくい。ということで、以下のようなスクリプトを用意して必要部分だけ抜き出してみる。
grep_exec.rb

#!/usr/bin/env ruby

flag = false
while gets
  if $_ =~ /CALL  execve/
    flag = true 
  end

  puts $_ if flag
  
  if $_ =~ /RET   execve/
    puts '...'
    flag = false
  end
end
$ kdump ktrace.out | ./grep_exec.rb
 25948 ktrace	CALL  execve(0xbfbfd686,0xbfbfd5a0,0xbfbfd5c0)
 25948 ktrace	NAMI  "/usr/bin/find"
 25948 ktrace	NAMI  "/usr/libexec/ld.elf_so"
 25948 find	EMUL  "netbsd"
 25948 find	RET   execve JUSTRETURN
...
 25949 find	CALL  execve(0xbfbfd69c,0x8057050,0xbfbfd5c8)
 25949 find	NAMI  "/usr/bin/grep"
 25949 find	NAMI  "/usr/libexec/ld.elf_so"
 25949 grep	EMUL  "netbsd"
 25949 grep	RET   execve JUSTRETURN
...
 25950 find	CALL  execve(0xbfbfd69c,0x8057050,0xbfbfd5c8)
 25950 find	NAMI  "/usr/bin/grep"
 25950 find	NAMI  "/usr/libexec/ld.elf_so"
 25950 grep	EMUL  "netbsd"
 25950 grep	RET   execve JUSTRETURN
...
 25951 find	CALL  execve(0xbfbfd69c,0x8057050,0xbfbfd5c8)
 25951 find	NAMI  "/usr/bin/grep"
 25951 find	NAMI  "/usr/libexec/ld.elf_so"
 25951 grep	EMUL  "netbsd"
 25951 grep	RET   execve JUSTRETURN
...
 25952 find	CALL  execve(0xbfbfd69c,0x8057050,0xbfbfd5c8)
 25952 find	NAMI  "/usr/bin/grep"
 25952 find	NAMI  "/usr/libexec/ld.elf_so"
 25952 grep	EMUL  "netbsd"
 25952 grep	RET   execve JUSTRETURN
...

ファイルとディレクトリは合計4つ(dir、a.txt、b.txt、c.txt)で、grepは4回呼出されているから、どうやらファイルとディレクトリが見付かる度にfork & execが行われているようだ。詳しくはソースを読む必要があるな。