เจฒเฉ€เจจเจ•เจธ เจตเจฟเฉฑเจš เจธเจŸเฉเจฐเฉˆเจธ: เจ‡เจคเจฟเจนเจพเจธ, เจกเจฟเจœเจผเจพเจˆเจจ เจ…เจคเฉ‡ เจตเจฐเจคเฉ‹เจ‚

เจฒเฉ€เจจเจ•เจธ เจตเจฟเฉฑเจš เจธเจŸเฉเจฐเฉˆเจธ: เจ‡เจคเจฟเจนเจพเจธ, เจกเจฟเจœเจผเจพเจˆเจจ เจ…เจคเฉ‡ เจตเจฐเจคเฉ‹เจ‚

เจฏเฉ‚เจจเจฟเจ•เจธ-เจตเจฐเจ—เฉ‡ เจ“เจชเจฐเฉ‡เจŸเจฟเฉฐเจ— เจธเจฟเจธเจŸเจฎเจพเจ‚ เจตเจฟเฉฑเจš, เจ‡เฉฑเจ• เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเจพ เจฌเจพเจนเจฐเฉ€ เจธเฉฐเจธเจพเจฐ เจ…เจคเฉ‡ เจ“เจชเจฐเฉ‡เจŸเจฟเฉฐเจ— เจธเจฟเจธเจŸเจฎ เจจเจพเจฒ เจธเฉฐเจšเจพเจฐ เจซเฉฐเจ•เจธเจผเจจเจพเจ‚ เจฆเฉ‡ เจ‡เฉฑเจ• เจ›เฉ‹เจŸเฉ‡ เจธเจฎเฉ‚เจน เจฆเฉเจ†เจฐเจพ เจนเฉเฉฐเจฆเจพ เจนเฉˆ - เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚เฅค เจ‡เจธเจฆเจพ เจฎเจคเจฒเจฌ เจ‡เจน เจนเฉˆ เจ•เจฟ เจกเฉ€เจฌเฉฑเจ—เจฟเฉฐเจ— เจ‰เจฆเฉ‡เจธเจผเจพเจ‚ เจฒเจˆ เจ‡เจน เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจฆเฉเจ†เจฐเจพ เจšเจฒเจพเจˆเจ†เจ‚ เจœเจพ เจฐเจนเฉ€เจ†เจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจœเจพเจธเฉ‚เจธเฉ€ เจ•เจฐเจจเจพ เจฒเจพเจญเจฆเจพเจ‡เจ• เจนเฉ‹ เจธเจ•เจฆเจพ เจนเฉˆเฅค

เจ‡เฉฑเจ• เจ‰เจชเจฏเฉ‹เจ—เจคเจพ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจฒเฉ€เจจเจ•เจธ 'เจคเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจฆเฉ‡ "เจ…เฉฐเจคเจฐเจœเจจ เจœเฉ€เจตเจจ" เจฆเฉ€ เจจเจฟเจ—เจฐเจพเจจเฉ€ เจ•เจฐเจจ เจตเจฟเฉฑเจš เจฎเจฆเจฆ เจ•เจฐเจฆเฉ€ เจนเฉˆ strace, เจœเฉ‹ เจ•เจฟ เจ‡เจธ เจฒเฉ‡เจ– เจฆเจพ เจตเจฟเจธเจผเจพ เจนเฉˆเฅค เจœเจพเจธเฉ‚เจธเฉ€ เจ‰เจชเจ•เจฐเจฃเจพเจ‚ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจฆเฉ€เจ†เจ‚ เจ‰เจฆเจพเจนเจฐเจฃเจพเจ‚ เจ‡เฉฑเจ• เจธเฉฐเจ–เฉ‡เจช เจ‡เจคเจฟเจนเจพเจธ เจฆเฉ‡ เจจเจพเจฒ เจนเจจ strace เจ…เจคเฉ‡ เจ…เจœเจฟเจนเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจฆเฉ‡ เจกเจฟเจœเจผเจพเจˆเจจ เจฆเจพ เจตเฉ‡เจฐเจตเจพเฅค

เจธเจฎเฉฑเจ—เจฐเฉ€

เจธเจชเฉ€เจธเฉ€เจœเจผ เจฆเจพ เจฎเฉ‚เจฒ

เจฏเฉ‚เจจเจฟเจ•เจธ เจตเจฟเฉฑเจš เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจ…เจคเฉ‡ OS เจ•เจฐเจจเจฒ เจตเจฟเจšเจ•เจพเจฐ เจฎเฉเฉฑเจ– เจ‡เฉฐเจŸเจฐเจซเฉ‡เจธ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจนเจจเฅค เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ, เจธเจพเจˆเจ•เจฒ), เจฌเจพเจนเจฐเฉ€ เจธเฉฐเจธเจพเจฐ เจจเจพเจฒ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจฆเฉ€ เจ†เจชเจธเฉ€ เจคเจพเจฒเจฎเฉ‡เจฒ เจตเจฟเจธเจผเฉ‡เจธเจผ เจคเฉŒเจฐ 'เจคเฉ‡ เจ‰เจนเจจเจพเจ‚ เจฆเฉเจ†เจฐเจพ เจนเฉเฉฐเจฆเฉ€ เจนเฉˆเฅค

เจชเจฐ เจฏเฉ‚เจจเจฟเจ•เจธ เจฆเฉ‡ เจชเจนเจฟเจฒเฉ‡ เจœเจจเจคเจ• เจธเฉฐเจธเจ•เจฐเจฃ เจตเจฟเฉฑเจš (เจธเฉฐเจธเจ•เจฐเจฃ 6 เจฏเฉ‚เจจเจฟเจ•เจธ, 1975) เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจฆเฉ‡ เจตเจฟเจตเจนเจพเจฐ เจจเฉ‚เฉฐ เจŸเจฐเฉˆเจ• เจ•เจฐเจจ เจฒเจˆ เจ•เฉ‹เจˆ เจธเฉเจตเจฟเจงเจพเจœเจจเจ• เจคเจฐเฉ€เจ•เฉ‡ เจจเจนเฉ€เจ‚ เจธเจจเฅค เจ‡เจธ เจฎเฉเฉฑเจฆเฉ‡ เจจเฉ‚เฉฐ เจนเฉฑเจฒ เจ•เจฐเจจ เจฒเจˆ, เจฌเฉˆเฉฑเจฒ เจฒเฉˆเจฌ เจ…เจ—เจฒเฉ‡ เจธเฉฐเจธเจ•เจฐเจฃ (เจธเฉฐเจธเจ•เจฐเจฃ 7 เจฏเฉ‚เจจเจฟเจ•เจธ, 1979) เจจเฉ‡ เจ‡เฉฑเจ• เจจเจตเฉ€เจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเจพ เจชเฉเจฐเจธเจคเจพเจต เจ•เฉ€เจคเจพ - ptrace.

ptrace เจฎเฉเฉฑเจ– เจคเฉŒเจฐ 'เจคเฉ‡ เจ‡เฉฐเจŸเจฐเจเจ•เจŸเจฟเจต เจกเฉ€เจฌเฉฑเจ—เจฐเจพเจ‚ เจฒเจˆ เจตเจฟเจ•เจธเจค เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจธเฉ€, เจชเจฐ 80 เจฆเฉ‡ เจฆเจนเจพเจ•เฉ‡ เจฆเฉ‡ เจ…เฉฐเจค เจคเฉฑเจ• (เจตเจชเจพเจฐเจ• เจฆเฉ‡ เจฏเฉเฉฑเจ— เจตเจฟเฉฑเจš เจธเจฟเจธเจŸเจฎ V เจฐเฉ€เจฒเฉ€เจœเจผ 4) เจ‡เจธ เจ†เจงเจพเจฐ 'เจคเฉ‡, เจ˜เฉฑเจŸ เจ•เฉ‡เจ‚เจฆเฉเจฐเจฟเจค เจกเฉ€เจฌเฉฑเจ—เจฐโ€”เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจŸเจฐเฉ‡เจธเจฐโ€”เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจนเฉ‹เจ เจ…เจคเฉ‡ เจตเจฟเจ†เจชเจ• เจคเฉŒเจฐ 'เจคเฉ‡ เจตเจฐเจคเฉ‡ เจ—เจเฅค

เจชเจนเจฟเจฒเจพ เจธเจŸเจฐเฉ‡เจธ เจฆเจพ เจ‰เจนเฉ€ เจธเฉฐเจธเจ•เจฐเจฃ เจชเจพเจฒ เจ•เฉเจฐเฉ‹เจจเฉ‡เจจเจฌเจฐเจ— เจฆเฉเจ†เจฐเจพ 1992 เจตเจฟเฉฑเจš เจฌเฉฐเจฆ เจ‰เจชเจฏเฉ‹เจ—เจคเจพ เจฆเฉ‡ เจตเจฟเจ•เจฒเจช เจตเจœเฉ‹เจ‚ comp.sources.sun เจฎเฉ‡เจฒเจฟเฉฐเจ— เจฒเจฟเจธเจŸ เจ‰เฉฑเจคเฉ‡ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจธเฉ€เฅค trace เจธเฉ‚เจฐเจœ เจคเฉ‹เจ‚. เจ•เจฒเฉ‹เจจ เจ…เจคเฉ‡ เจ…เจธเจฒเฉ€ เจฆเฉ‹เจตเฉ‡เจ‚ เจธเจจเฉ‹เจธ เจฒเจˆ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเฉ‡ เจ—เจ เจธเจจ, เจชเจฐ 1994 เจคเฉฑเจ• strace เจธเจฟเจธเจŸเจฎ V, เจธเฉ‹เจฒเจพเจฐเจฟเจธ เจ…เจคเฉ‡ เจตเจงเจฆเฉ‡ เจชเฉเจฐเจธเจฟเฉฑเจง เจฒเฉ€เจจเจ•เจธ เจฒเจˆ เจชเฉ‹เจฐเจŸ เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจธเฉ€เฅค

เจ…เฉฑเจœ เจธเจŸเฉเจฐเฉˆเจธ เจธเจฟเจฐเจซเจผ เจฒเฉ€เจจเจ•เจธ เจฆเจพ เจธเจฎเจฐเจฅเจจ เจ•เจฐเจฆเจพ เจนเฉˆ เจ…เจคเฉ‡ เจ‰เจธเฉ‡ 'เจคเฉ‡ เจจเจฟเจฐเจญเจฐ เจ•เจฐเจฆเจพ เจนเฉˆ ptrace, เจฌเจนเฉเจค เจธเจพเจฐเฉ‡ เจเจ•เจธเจŸเฉˆเจ‚เจธเจผเจจเจพเจ‚ เจจเจพเจฒ เจตเจงเจฟเจ† เจนเฉ‹เจ‡เจ† เจนเฉˆเฅค

เจ†เจงเฉเจจเจฟเจ• (เจ…เจคเฉ‡ เจฌเจนเฉเจค เจธเจฐเจ—เจฐเจฎ) เจฐเฉฑเจ–-เจฐเจ–เจพเจ… เจ•เจฐเจจ เจตเจพเจฒเจพ strace - เจฆเจฎเจฟเจคเจฐเฉ€ เจฒเฉ‡เจตเจฟเจจ. เจ‰เจธเจฆเฉ‡ เจฒเจˆ เจงเฉฐเจจเจตเจพเจฆ, เจ‰เจชเจฏเฉ‹เจ—เจคเจพ เจจเฉ‡ เจคเจ•เจจเฉ€เจ•เฉ€ เจตเจฟเจธเจผเฉ‡เจธเจผเจคเจพเจตเจพเจ‚ เจชเฉเจฐเจพเจชเจค เจ•เฉ€เจคเฉ€เจ†เจ‚ เจœเจฟเจตเฉ‡เจ‚ เจ•เจฟ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจตเจฟเฉฑเจš เจ—เจฒเจคเฉ€ เจ‡เฉฐเจœเฉˆเจ•เจธเจผเจจ, เจ†เจฐเจ•เฉ€เจŸเฉˆเจ•เจšเจฐ เจฆเฉ€ เจ‡เฉฑเจ• เจตเจฟเจธเจผเจพเจฒ เจธเจผเฉเจฐเฉ‡เจฃเฉ€ เจฒเจˆ เจธเจฎเจฐเจฅเจจ เจ…เจคเฉ‡, เจธเจญ เจคเฉ‹เจ‚ เจฎเจนเฉฑเจคเจตเจชเฉ‚เจฐเจจ, เจฎเจพเจธเจ•เฉŒเจŸ. เจ…เจฃเจ…เจงเจฟเจ•เจพเจฐเจค เจธเจฐเฉ‹เจคเจพเจ‚ เจฆเจพ เจฆเจพเจ…เจตเจพ เจนเฉˆ เจ•เจฟ เจฐเฉ‚เจธเฉ€ เจธเจผเจฌเจฆ "เจธเจผเฉเจคเจฐเจฎเฉเจฐเจ—" เจ…เจคเฉ‡ เจ…เฉฐเจ—เจฐเฉ‡เจœเจผเฉ€ เจธเจผเจฌเจฆ "เจธเจŸเจฐเฉ‡เจธ" เจฆเฉ‡ เจตเจฟเจšเจ•เจพเจฐ เจตเจฟเจ…เฉฐเจœเจจ เจฆเฉ‡ เจ•เจพเจฐเจจ เจšเฉ‹เจฃ เจธเจผเฉเจคเจฐเจฎเฉเจฐเจ— 'เจคเฉ‡ เจกเจฟเฉฑเจ— เจ—เจˆเฅค

เจ‡เจน เจตเฉ€ เจฎเจนเฉฑเจคเจตเจชเฉ‚เจฐเจจ เจนเฉˆ เจ•เจฟ เจฒเฉ€เจจเจ•เจธ, เจซเฉเจฐเฉ€เจฌเฉ€เจเจธเจกเฉ€, เจ“เจชเจจเจฌเฉ€เจเจธเจกเฉ€ เจ…เจคเฉ‡ เจฐเจตเจพเจ‡เจคเฉ€ เจฏเฉ‚เจจเจฟเจ•เจธ เจตเจฟเฉฑเจš เจฒเฉฐเจฌเฉ‡ เจ‡เจคเจฟเจนเจพเจธ เจ…เจคเฉ‡ เจฒเจพเจ—เฉ‚ เจนเฉ‹เจฃ เจฆเฉ‡ เจฌเจพเจตเจœเฉ‚เจฆ, ptrace เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจ…เจคเฉ‡ เจŸเจฐเฉ‡เจธเจฐ เจ•เจฆเฉ‡ เจตเฉ€ POSIX เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจจเจนเฉ€เจ‚ เจ•เฉ€เจคเฉ‡ เจ—เจ เจธเจจเฅค

เจธเฉฐเจ–เฉ‡เจช เจตเจฟเฉฑเจš เจธเจŸเฉเจฐเฉˆเจธ เจกเจฟเจตเจพเจˆเจธ: เจชเจฟเจ—เจฒเฉ‡เจŸ เจŸเจฐเฉ‡เจธ

"เจคเฉเจนเจพเจกเฉ‡ เจคเฉ‹เจ‚ เจ‡เจน เจธเจฎเจเจฃ เจฆเฉ€ เจ‰เจฎเฉ€เจฆ เจจเจนเฉ€เจ‚ เจนเฉˆ" (เจกเฉˆเจจเจฟเจธ เจฐเจฟเจšเฉ€, เจธเฉฐเจธเจ•เจฐเจฃ 6 เจฏเฉ‚เจจเจฟเจ•เจธ เจธเจฐเฉ‹เจค เจ•เฉ‹เจก เจตเจฟเฉฑเจš เจŸเจฟเฉฑเจชเจฃเฉ€)

เจฌเจšเจชเจจ เจคเฉ‹เจ‚ เจนเฉ€, เจฎเฉˆเจ‚ เจฌเจฒเฉˆเจ• เจฌเจพเจ•เจธ เจจเฉ‚เฉฐ เจ–เฉœเจพ เจจเจนเฉ€เจ‚ เจ•เจฐ เจธเจ•เจฆเจพ: เจฎเฉˆเจ‚ เจ–เจฟเจกเฉŒเจฃเจฟเจ†เจ‚ เจจเจพเจฒ เจจเจนเฉ€เจ‚ เจ–เฉ‡เจกเจฟเจ†, เจชเจฐ เจ‰เจนเจจเจพเจ‚ เจฆเฉ€ เจฌเจฃเจคเจฐ เจจเฉ‚เฉฐ เจธเจฎเจเจฃ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เฉ€เจคเฉ€ (เจฌเจพเจฒเจ—เจพเจ‚ เจจเฉ‡ "เจŸเฉเฉฑเจŸเจฟเจ†" เจธเจผเจฌเจฆ เจตเจฐเจคเจฟเจ†, เจชเจฐ เจฌเฉเจฐเจพเจˆเจ†เจ‚ 'เจคเฉ‡ เจตเจฟเจธเจผเจตเจพเจธ เจจเจพ เจ•เจฐเฉ‹)เฅค เจธเจผเจพเจ‡เจฆ เจ‡เจนเฉ€ เจ•เจพเจฐเจจ เจนเฉˆ เจ•เจฟ เจชเจนเจฟเจฒเฉ‡ เจฏเฉ‚เจจเจฟเจ•เจธ เจ…เจคเฉ‡ เจ†เจงเฉเจจเจฟเจ• เจ“เจชเจจ-เจธเฉ‹เจฐเจธ เจ…เฉฐเจฆเฉ‹เจฒเจจ เจฆเจพ เจ—เฉˆเจฐ เจฐเจธเจฎเฉ€ เจธเฉฑเจญเจฟเจ†เจšเจพเจฐ เจฎเฉ‡เจฐเฉ‡ เจฌเจนเฉเจค เจจเฉ‡เฉœเฉ‡ เจนเฉˆเฅค

เจ‡เจธ เจฒเฉ‡เจ– เจฆเฉ‡ เจ‰เจฆเฉ‡เจธเจผเจพเจ‚ เจฒเจˆ, เจธเจŸเฉเจฐเฉˆเจธ เจฆเฉ‡ เจธเจฐเฉ‹เจค เจ•เฉ‹เจก เจจเฉ‚เฉฐ เจตเฉฑเจ– เจ•เจฐเจจเจพ เจ—เฉˆเจฐ-เจตเจพเจœเจฌ เจนเฉˆ, เจœเฉ‹ เจฆเจนเจพเจ•เจฟเจ†เจ‚ เจคเฉ‹เจ‚ เจตเจงเจฟเจ† เจนเฉˆเฅค เจชเจฐ เจชเจพเจ เจ•เจพเจ‚ เจฒเจˆ เจ•เฉ‹เจˆ เจญเฉ‡เจค เจจเจนเฉ€เจ‚ เจ›เฉฑเจกเจฃเจพ เจšเจพเจนเฉ€เจฆเจพเฅค เจ‡เจธ เจฒเจˆ, เจ…เจœเจฟเจนเฉ‡ เจธเจŸเจฐเฉ‡เจธ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจฆเฉ‡ เจธเฉฐเจšเจพเจฒเจจ เจฆเฉ‡ เจธเจฟเจงเจพเจ‚เจค เจจเฉ‚เฉฐ เจฆเจฐเจธเจพเจ‰เจฃ เจฒเจˆ, เจฎเฉˆเจ‚ เจ‡เฉฑเจ• เจ›เฉ‹เจŸเฉ‡ เจŸเจฐเฉ‡เจธเจฐ เจฒเจˆ เจ•เฉ‹เจก เจชเฉเจฐเจฆเจพเจจ เจ•เจฐเจพเจ‚เจ—เจพ - เจชเจฟเจ—เจฒเฉ‡เจŸ เจŸเจฐเฉ‡เจธ (ptr)เฅค เจ‡เจน เจจเจนเฉ€เจ‚ เจœเจพเจฃเจฆเจพ เจ•เจฟ เจ•เฉเจ เจ–เจพเจธ เจ•เจฟเจตเฉ‡เจ‚ เจ•เจฐเจจเจพ เจนเฉˆ, เจชเจฐ เจฎเฉเฉฑเจ– เจ—เฉฑเจฒ เจ‡เจน เจนเฉˆ เจ•เจฟ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€เจ†เจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ - เจ‡เจน เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจ•เจฐเจฆเจพ เจนเฉˆ:

$ gcc examples/piglet-trace.c -o ptr
$ ptr echo test > /dev/null
BRK(12) -> 94744690540544
ACCESS(21) -> 18446744073709551614
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694657216512
CLOSE(3) -> 0
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
READ(0) -> 832
FSTAT(5) -> 0
MMAP(9) -> 140694657208320
MMAP(9) -> 140694650953728
MPROTECT(10) -> 0
MMAP(9) -> 140694655045632
MMAP(9) -> 140694655070208
CLOSE(3) -> 0
unknown(158) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MUNMAP(11) -> 0
BRK(12) -> 94744690540544
BRK(12) -> 94744690675712
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694646390784
CLOSE(3) -> 0
FSTAT(5) -> 0
IOCTL(16) -> 18446744073709551591
WRITE(1) -> 5
CLOSE(3) -> 0
CLOSE(3) -> 0
unknown(231)
Tracee terminated

เจชเจฟเจ—เจฒเฉ‡เจŸ เจŸเจฐเฉ‡เจธ เจฒเจ—เจญเจ— เจธเฉˆเจ‚เจ•เฉœเฉ‡ เจฒเฉ€เจจเจ•เจธ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจชเจ›เจพเจฃเจฆเจพ เจนเฉˆ (เจตเฉ‡เจ–เฉ‹. เจฎเฉ‡เจœเจผ) เจ…เจคเฉ‡ เจธเจฟเจฐเจซเจผ x86-64 เจ†เจฐเจ•เฉ€เจŸเฉˆเจ•เจšเจฐ 'เจคเฉ‡ เจ•เฉฐเจฎ เจ•เจฐเจฆเจพ เจนเฉˆเฅค เจ‡เจน เจตเจฟเจฆเจฟเจ…เจ• เจ‰เจฆเฉ‡เจธเจผเจพเจ‚ เจฒเจˆ เจ•เจพเจซเฉ€ เจนเฉˆเฅค

เจ†เจ“ เจ†เจชเจฃเฉ‡ เจ•เจฒเฉ‹เจจ เจฆเฉ‡ เจ•เฉฐเจฎ เจจเฉ‚เฉฐ เจตเฉ‡เจ–เฉ€เจ. เจฒเฉ€เจจเจ•เจธ เจฆเฉ‡ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš, เจกเฉ€เจฌเฉฑเจ—เจฐ เจ…เจคเฉ‡ เจŸเจฐเฉ‡เจธเจฐ, เจœเจฟเจตเฉ‡เจ‚ เจ•เจฟ เจ‰เฉฑเจชเจฐ เจฆเฉฑเจธเจฟเจ† เจ—เจฟเจ† เจนเฉˆ, ptrace เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเจจเฅค เจ‡เจน เจชเจนเจฟเจฒเฉ€ เจ†เจฐเจ—เฉ‚เจฎเฉˆเจ‚เจŸ เจตเจฟเฉฑเจš เจ•เจฎเจพเจ‚เจก เจชเจ›เจพเจฃเจ•เจฐเจคเจพ เจจเฉ‚เฉฐ เจชเจพเจธ เจ•เจฐเจ•เฉ‡ เจ•เฉฐเจฎ เจ•เจฐเจฆเจพ เจนเฉˆ, เจœเจฟเจธเจฆเฉ€ เจธเจพเจจเฉ‚เฉฐ เจธเจฟเจฐเจซเจผ เจฒเฉ‹เฉœ เจนเฉˆ PTRACE_TRACEME, PTRACE_SYSCALL ะธ PTRACE_GETREGS.

เจŸเจฐเฉ‡เจธเจฐ เจ†เจฎ เจฏเฉ‚เจจเจฟเจ•เจธ เจธเจผเฉˆเจฒเฉ€ เจตเจฟเฉฑเจš เจธเจผเฉเจฐเฉ‚ เจนเฉเฉฐเจฆเจพ เจนเฉˆ: fork(2) เจ‡เฉฑเจ• เจšเจพเจˆเจฒเจก เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจธเจผเฉเจฐเฉ‚ เจ•เจฐเจฆเจพ เจนเฉˆ, เจœเฉ‹ เจฌเจฆเจฒเฉ‡ เจตเจฟเฉฑเจš เจตเจฐเจคเจฆเจพ เจนเฉˆ exec(3) เจ…เจงเจฟเจเจจ เจ…เจงเฉ€เจจ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€ เจธเจผเฉเจฐเฉ‚เจ†เจค เจ•เจฐเจฆเจพ เจนเฉˆเฅค เจ‡เฉฑเจฅเฉ‡ เจธเจฟเจฐเจซ เจธเฉ‚เจ–เจฎเจคเจพ เจšเฉเจฃเฉŒเจคเฉ€ เจนเฉˆ ptrace(PTRACE_TRACEME) ะฟะตั€ะตะด exec: เจฌเจพเจฒ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฎเจพเจคเจพ-เจชเจฟเจคเจพ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจคเฉ‹เจ‚ เจ‡เจธเจฆเฉ€ เจจเจฟเจ—เจฐเจพเจจเฉ€ เจ•เจฐเจจ เจฆเฉ€ เจ‰เจฎเฉ€เจฆ เจ•เจฐเจฆเฉ€ เจนเฉˆ:

pid_t child_pid = fork();
switch (child_pid) {
case -1:
    err(EXIT_FAILURE, "fork");
case 0:
    /* Child here */
    /* A traced mode has to be enabled. A parent will have to wait(2) for it
     * to happen. */
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    /* Replace itself with a program to be run. */
    execvp(argv[1], argv + 1);
    err(EXIT_FAILURE, "exec");
}

เจฎเจพเจคเจพ-เจชเจฟเจคเจพ เจฆเฉ€ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจจเฉ‚เฉฐ เจนเฉเจฃ เจ•เจพเจฒ เจ•เจฐเจจเจพ เจšเจพเจนเฉ€เจฆเจพ เจนเฉˆ wait(2) เจšเจพเจˆเจฒเจก เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจตเจฟเฉฑเจš, เจฏเจพเจจเฉ€, เจฏเจ•เฉ€เจจเฉ€ เจฌเจฃเจพเจ“ เจ•เจฟ เจŸเจฐเฉ‡เจธ เจฎเฉ‹เจก เจตเจฟเฉฑเจš เจธเจตเจฟเจš เจ•เจฐเจจเจพ เจนเฉ‹เจ‡เจ† เจนเฉˆ:

/* Parent */

/* First we wait for the child to set the traced mode (see
 * ptrace(PTRACE_TRACEME) above) */
if (waitpid(child_pid, NULL, 0) == -1)
    err(EXIT_FAILURE, "traceme -> waitpid");

เจ‡เจธ เจธเจฎเฉ‡เจ‚, เจคเจฟเจ†เจฐเฉ€เจ†เจ‚ เจชเฉ‚เจฐเฉ€เจ†เจ‚ เจนเฉ‹ เจ—เจˆเจ†เจ‚ เจนเจจ เจ…เจคเฉ‡ เจคเฉเจธเฉ€เจ‚ เจ‡เฉฑเจ• เจฌเฉ‡เจ…เฉฐเจค เจฒเฉ‚เจช เจตเจฟเฉฑเจš เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจŸเจฐเฉˆเจ• เจ•เจฐเจจ เจฒเจˆ เจธเจฟเฉฑเจงเฉ‡ เจ…เฉฑเจ—เฉ‡ เจตเจง เจธเจ•เจฆเฉ‡ เจนเฉ‹เฅค

เจšเฉเจฃเฉŒเจคเฉ€ ptrace(PTRACE_SYSCALL) เจ‡เจธ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ เจฆเฉ€ เจ—เจพเจฐเฉฐเจŸเฉ€ เจฆเจฟเฉฐเจฆเจพ เจนเฉˆ wait เจฎเจพเจคเจพ เจœเจพเจ‚ เจคเจพเจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ‡ เจเจ—เจœเจผเฉ€เจ•เจฟเจŠเจŸ เจนเฉ‹เจฃ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚ เจœเจพเจ‚ เจ‡เจธ เจฆเฉ‡ เจชเฉ‚เจฐเจพ เจนเฉ‹เจฃ เจคเฉ‹เจ‚ เจคเฉเจฐเฉฐเจค เจฌเจพเจ…เจฆ เจชเฉ‚เจฐเจพ เจนเฉ‹ เจœเจพเจตเฉ‡เจ—เจพเฅค เจฆเฉ‹ เจ•เจพเจฒเจพเจ‚ เจฆเฉ‡ เจตเจฟเจšเจ•เจพเจฐ เจคเฉเจธเฉ€เจ‚ เจ•เฉ‹เจˆ เจตเฉ€ เจ•เจพเจฐเจตเจพเจˆเจ†เจ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹: เจ•เจพเจฒ เจจเฉ‚เฉฐ เจ•เจฟเจธเฉ‡ เจตเจฟเจ•เจฒเจชเจ• เจจเจพเจฒ เจฌเจฆเจฒเฉ‹, เจ†เจฐเจ—เฉ‚เจฎเฉˆเจ‚เจŸเจธ เจœเจพเจ‚ เจตเจพเจชเจธเฉ€ เจฎเฉเฉฑเจฒ เจฌเจฆเจฒเฉ‹เฅค

เจธเจพเจจเฉ‚เฉฐ เจธเจฟเจฐเจซเจผ เจฆเฉ‹ เจตเจพเจฐ เจ•เจฎเจพเจ‚เจก เจจเฉ‚เฉฐ เจ•เจพเจฒ เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ ptrace(PTRACE_GETREGS)เจฐเจœเจฟเจธเจŸเจฐ เจฐเจพเจœ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจ เจฒเจˆ rax เจ•เจพเจฒ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚ (เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจจเฉฐเจฌเจฐ) เจ…เจคเฉ‡ เจคเฉเจฐเฉฐเจค เจฌเจพเจ…เจฆ (เจตเจพเจชเจธเฉ€ เจฎเฉเฉฑเจฒ)เฅค

เจ…เจธเจฒ เจตเจฟเฉฑเจš, เจšเฉฑเจ•เจฐ:

/* A system call tracing loop, one interation per call. */
for (;;) {
    /* A non-portable structure defined for ptrace/GDB/strace usage mostly.
     * It allows to conveniently dump and access register state using
     * ptrace. */
    struct user_regs_struct registers;

    /* Enter syscall: continue execution until the next system call
     * beginning. Stop right before syscall.
     *
     * It's possible to change the system call number, system call
     * arguments, return value or even avoid executing the system call
     * completely. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "enter_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "enter_syscall -> waitpid");

  /* According to the x86-64 system call convention on Linux (see man 2
   * syscall) the number identifying a syscall should be put into the rax
   * general purpose register, with the rest of the arguments residing in
   * other general purpose registers (rdi,rsi, rdx, r10, r8, r9). */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1)
      err(EXIT_FAILURE, "enter_syscall -> getregs");

  /* Note how orig_rax is used here. That's because on x86-64 rax is used
   * both for executing a syscall, and returning a value from it. To
   * differentiate between the cases both rax and orig_rax are updated on
   * syscall entry/exit, and only rax is updated on exit. */
  print_syscall_enter(registers.orig_rax);

  /* Exit syscall: execute of the syscall, and stop on system
   * call exit.
   *
   * More system call tinkering possible: change the return value, record
   * time it took to finish the system call, etc. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "exit_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "exit_syscall -> waitpid");

  /* Retrieve register state again as we want to inspect system call
   * return value. */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1) {
      /* ESRCH is returned when a child terminates using a syscall and no
       * return value is possible, e.g. as a result of exit(2). */
      if (errno == ESRCH) {
          fprintf(stderr, "nTracee terminatedn");
          break;
      }
      err(EXIT_FAILURE, "exit_syscall -> getregs");
  }

  /* Done with this system call, let the next iteration handle the next
   * one */
  print_syscall_exit(registers.rax);
}

เจ‡เจน เจธเจพเจฐเจพ เจŸเจฐเฉ‡เจธเจฐ เจนเฉˆเฅค เจนเฉเจฃ เจคเฉเจธเฉ€เจ‚ เจœเจพเจฃเจฆเฉ‡ เจนเฉ‹ เจ•เจฟ เจ…เจ—เจฒเฉ€ เจชเฉ‹เจฐเจŸเจฟเฉฐเจ— เจ•เจฟเฉฑเจฅเฉ‹เจ‚ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเจจเฉ€ เจนเฉˆ เจกเฉ€เจŸเจฐเฉ‡เจธ เจฒเฉ€เจจเจ•เจธ 'เจคเฉ‡.

เจฌเฉเจจเจฟเจ†เจฆ: เจ‡เฉฑเจ• เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจšเฉฑเจฒ เจฐเจฟเจนเจพ strace เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃเจพ

เจชเจนเจฟเจฒเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจฆเฉ‡ เจ•เฉ‡เจธ เจตเจœเฉ‹เจ‚ strace, เจธเจผเจพเจ‡เจฆ เจ‡เจน เจธเจญ เจคเฉ‹เจ‚ เจธเจฐเจฒ เจตเจฟเจงเฉ€ เจฆเจพ เจนเจตเจพเจฒเจพ เจฆเฉ‡เจฃ เจฆเฉ‡ เจฏเฉ‹เจ— เจนเฉˆ - เจšเฉฑเจฒ เจฐเจนเฉ€ เจ‡เฉฑเจ• เจเจชเจฒเฉ€เจ•เฉ‡เจธเจผเจจ เจจเฉ‚เฉฐ เจฒเจพเจ‚เจš เจ•เจฐเจจเจพ strace.

เจ‡เฉฑเจ• เจ†เจฎ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€เจ†เจ‚ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจฌเฉ‡เจ…เฉฐเจค เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจจเจพ เจœเจพเจฃ เจฒเจˆ, เจ…เจธเฉ€เจ‚ เจฒเจฟเจ–เจฆเฉ‡ เจนเจพเจ‚ เจ˜เฉฑเจŸเฉ‹-เจ˜เฉฑเจŸ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจ†เจฒเฉ‡ เจฆเฉเจ†เจฒเฉ‡ write:

int main(int argc, char *argv[])
{
    char str[] = "write me to stdoutn";
    /* write(2) is a simple wrapper around a syscall so it should be easy to
     * find in the syscall trace. */
    if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
        perror("write");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

เจ†เจ‰ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฌเจฃเจพเจ‰ เจ…เจคเฉ‡ เจฏเจ•เฉ€เจจเฉ€ เจฌเจฃเจพเจ“ เจ•เจฟ เจ‡เจน เจ•เฉฐเจฎ เจ•เจฐเจฆเจพ เจนเฉˆ:

$ gcc examples/write-simple.c -o write-simple
$ ./write-simple
write me to stdout

เจ…เจคเฉ‡ เจ…เฉฐเจค เจตเจฟเฉฑเจš, เจ†เจ“ เจ‡เจธเจจเฉ‚เฉฐ เจธเจŸเฉเจฐเฉˆเจธ เจจเจฟเจฏเฉฐเจคเจฐเจฃ เจตเจฟเฉฑเจš เจšเจฒเจพเจˆเจ:

$ strace ./write-simple
pexecve("./write", ["./write"], 0x7ffebd6145b0 /* 71 vars */) = 0
brk(NULL)                               = 0x55ff5489e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=197410, ...}) = 0
mmap(NULL, 197410, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7a2a633000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a631000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7a2a04c000
mprotect(0x7f7a2a233000, 2097152, PROT_NONE) = 0
mmap(0x7f7a2a433000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f7a2a433000
mmap(0x7f7a2a439000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a439000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f7a2a6324c0) = 0
mprotect(0x7f7a2a433000, 16384, PROT_READ) = 0
mprotect(0x55ff52b52000, 4096, PROT_READ) = 0
mprotect(0x7f7a2a664000, 4096, PROT_READ) = 0
munmap(0x7f7a2a633000, 197410)          = 0
write(1, "write me to stdoutn", 20write me to stdout
)  = 20
exit_group(0)                           = ?

เจฌเจนเฉเจค "เจธเจผเจฌเจฆ" เจ…เจคเฉ‡ เจฌเจนเฉเจค เจตเจฟเจฆเจฟเจ…เจ• เจจเจนเฉ€เจ‚เฅค เจ‡เฉฑเจฅเฉ‡ เจฆเฉ‹ เจธเจฎเฉฑเจธเจฟเจ†เจตเจพเจ‚ เจนเจจ: เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจจเฉ‚เฉฐ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจจเจพเจฒ เจฎเจฟเจฒเจพเจ‡เจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ strace เจ…เจคเฉ‡ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจฌเจนเฉเจคเจพเจค เจœเฉ‹ เจธเจพเจกเฉ€ เจฆเจฟเจฒเจšเจธเจชเฉ€ เจจเจนเฉ€เจ‚ เจฐเฉฑเจ–เจฆเฉ‡เฅค

เจคเฉเจธเฉ€เจ‚ -o เจธเจตเจฟเฉฑเจš เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€ เจธเจŸเฉˆเจ‚เจกเจฐเจก เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจธเจŸเฉเจฐเฉ€เจฎ เจ…เจคเฉ‡ เจธเจŸเฉเจฐเฉˆเจธ เจเจฐเจฐ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจจเฉ‚เฉฐ เจตเฉฑเจ– เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹, เจœเฉ‹ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจธเฉ‚เจšเฉ€ เจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจ†เจฐเจ—เฉ‚เจฎเฉˆเจ‚เจŸ เจซเจพเจˆเจฒ เจตเจฟเฉฑเจš เจฐเฉ€เจกเจพเจ‡เจฐเฉˆเจ•เจŸ เจ•เจฐเจฆเจพ เจนเฉˆเฅค

เจ‡เจน "เจตเจพเจงเฉ‚" เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจธเจฎเฉฑเจธเจฟเจ† เจจเจพเจฒ เจจเจœเจฟเฉฑเจ เจฃเจพ เจฌเจพเจ•เฉ€ เจนเฉˆเฅค เจšเจฒเฉ‹ เจ‡เจน เจฎเฉฐเจจ เจฒเจ“ เจ•เจฟ เจ…เจธเฉ€เจ‚ เจธเจฟเจฐเจซ เจ•เจพเจฒเจพเจ‚ เจตเจฟเฉฑเจš เจฆเจฟเจฒเจšเจธเจชเฉ€ เจฐเฉฑเจ–เจฆเฉ‡ เจนเจพเจ‚ write. เจ•เฉเฉฐเจœเฉ€ -e เจคเฉเจนเจพเจจเฉ‚เฉฐ เจธเจฎเฉ€เจ•เจฐเจจ เจจเจฟเจฐเจงเจพเจฐเจค เจ•เจฐเจจ เจฆเฉ€ เจ‡เจœเจพเจœเจผเจค เจฆเจฟเฉฐเจฆเจพ เจนเฉˆ เจœเจฟเจธ เจฆเฉเจ†เจฐเจพ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจซเจฟเจฒเจŸเจฐ เจ•เฉ€เจคเจพ เจœเจพเจตเฉ‡เจ—เจพเฅค เจธเจญ เจคเฉ‹เจ‚ เจชเฉเจฐเจธเจฟเฉฑเจง เจธเจฅเจฟเจคเฉ€ เจตเจฟเจ•เจฒเจช เจนเฉˆ, เจ•เฉเจฆเจฐเจคเฉ€ เจคเฉŒเจฐ 'เจคเฉ‡, trace=*, เจœเจฟเจธ เจจเจพเจฒ เจคเฉเจธเฉ€เจ‚ เจธเจฟเจฐเจซเจผ เจ‰เจนเจจเจพเจ‚ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจ›เฉฑเจก เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจœเฉ‹ เจธเจพเจกเฉ€ เจฆเจฟเจฒเจšเจธเจชเฉ€ เจฐเฉฑเจ–เจฆเฉ‡ เจนเจจเฅค

เจœเจฆเฉ‹เจ‚ เจ‡เฉฑเจ•เฉ‹ เจธเจฎเฉ‡เจ‚ เจตเจฐเจคเจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ -o ะธ -e เจธเจพเจจเฉ‚เฉฐ เจฎเจฟเจฒเฉ‡เจ—เจพ:

$ strace -e trace=write -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20
)  = 20
+++ exited with 0 +++

เจ‡เจธ เจฒเจˆ, เจคเฉเจธเฉ€เจ‚ เจฆเฉ‡เจ–เฉ‹, เจ‡เจน เจชเฉœเฉเจนเจจเจพ เจฌเจนเฉเจค เจธเฉŒเจ–เจพ เจนเฉˆ.

เจคเฉเจธเฉ€เจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจตเฉ€ เจนเจŸเจพ เจธเจ•เจฆเฉ‡ เจนเฉ‹, เจ‰เจฆเจพเจนเจฐเจจ เจฒเจˆ เจœเฉ‹ เจฎเฉˆเจฎเฉ‹เจฐเฉ€ เจตเฉฐเจก เจ…เจคเฉ‡ เจ–เจพเจฒเฉ€ เจ•เจฐเจจ เจจเจพเจฒ เจธเจฌเฉฐเจงเจค เจนเจจ:

$ strace -e trace=!brk,mmap,mprotect,munmap -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
execve("./write-simple", ["./write-simple"], 0x7ffe9972a498 /* 69 vars */) = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=124066, ...}) = 0
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f00f0be74c0) = 0
write(1, "write me to stdoutn", 20)  = 20
exit_group(0)                           = ?
+++ exited with 0 +++

เจ•เฉฑเจขเฉ€เจ†เจ‚ เจ—เจˆเจ†เจ‚ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจฌเจšเฉ‡ เจตเจฟเจธเจฎเจฟเจ• เจšเจฟเฉฐเจจเฉเจน เจจเฉ‚เฉฐ เจจเฉ‹เจŸ เจ•เจฐเฉ‹: เจ‡เจน เจ•เจฎเจพเจ‚เจก เจธเจผเฉˆเฉฑเจฒ เจฆเฉเจ†เจฐเจพ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเจพ เจนเฉˆเฅค เจธเจผเฉˆเฉฑเจฒ).

glibc เจฆเฉ‡ เจฎเฉ‡เจฐเฉ‡ เจธเฉฐเจธเจ•เจฐเจฃ เจตเจฟเฉฑเจš, เจ‡เฉฑเจ• เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจจเฉ‚เฉฐ เจ–เจคเจฎ เจ•เจฐ เจฆเจฟเฉฐเจฆเฉ€ เจนเฉˆ exit_group, เจฐเจตเจพเจ‡เจคเฉ€ เจจเจนเฉ€เจ‚ _exit. เจ‡เจน เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเจพเจฒ เจ•เฉฐเจฎ เจ•เจฐเจจ เจฆเฉ€ เจฎเฉเจธเจผเจ•เจฒ เจนเฉˆ: เจ‡เฉฐเจŸเจฐเจซเฉ‡เจธ เจœเจฟเจธ เจจเจพเจฒ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจฐ เจ•เฉฐเจฎ เจ•เจฐเจฆเจพ เจนเฉˆ, เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเจพเจฒ เจธเจฟเฉฑเจงเฉ‡ เจคเฉŒเจฐ 'เจคเฉ‡ เจธเฉฐเจฌเฉฐเจงเจฟเจค เจจเจนเฉ€เจ‚ เจนเฉˆเฅค เจ‡เจธ เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, เจ‡เจน เจฒเจพเจ—เฉ‚ เจ•เจฐเจจ เจ…เจคเฉ‡ เจชเจฒเฉ‡เจŸเจซเจพเจฐเจฎ 'เจคเฉ‡ เจจเจฟเจฐเจญเจฐ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจจเจฟเจฏเจฎเจฟเจค เจคเฉŒเจฐ 'เจคเฉ‡ เจฌเจฆเจฒเจฆเจพ เจนเฉˆเฅค

เจฌเฉเจจเจฟเจ†เจฆ: เจ‰เฉฑเจกเจฆเฉ‡ เจนเฉ‹เจ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจนเฉ‹เจฃเจพ

เจธเจผเฉเจฐเฉ‚ เจตเจฟเฉฑเจš, ptrace เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจœเจฟเจธ 'เจคเฉ‡ เจ‡เจธ เจจเฉ‚เฉฐ เจฌเจฃเจพเจ‡เจ† เจ—เจฟเจ† เจธเฉ€ strace, เจธเจฟเจฐเจซ เจ‰เจฆเฉ‹เจ‚ เจตเจฐเจคเจฟเจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆ เจœเจฆเฉ‹เจ‚ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจตเจฟเจธเจผเฉ‡เจธเจผ เจฎเฉ‹เจก เจตเจฟเฉฑเจš เจšเจฒเจพเจ‡เจ† เจœเจพ เจฐเจฟเจนเจพ เจนเฉ‹เจตเฉ‡เฅค เจธเฉฐเจธเจ•เจฐเจฃ 6 เจฏเฉ‚เจจเจฟเจ•เจธ เจฆเฉ‡ เจฆเจฟเจจเจพเจ‚ เจตเจฟเฉฑเจš เจ‡เจน เจธเฉ€เจฎเจพ เจตเจพเจœเจฌ เจฒเฉฑเจ— เจธเจ•เจฆเฉ€ เจนเฉˆเฅค เจ…เฉฑเจœเจ•เฉฑเจฒเฉเจน, เจ‡เจน เจนเฉเจฃ เจ•เจพเจซเจผเฉ€ เจจเจนเฉ€เจ‚ เจนเฉˆ: เจ•เจˆ เจตเจพเจฐ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ•เจพเจฐเจœเจธเจผเฉ€เจฒ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€เจ†เจ‚ เจธเจฎเฉฑเจธเจฟเจ†เจตเจพเจ‚ เจฆเฉ€ เจœเจพเจ‚เจš เจ•เจฐเจจ เจฆเฉ€ เจœเจผเจฐเฉ‚เจฐเจค เจนเฉเฉฐเจฆเฉ€ เจนเฉˆ. เจ‡เฉฑเจ• เจ–เจพเจธ เจ‰เจฆเจพเจนเจฐเจจ เจนเฉˆเจ‚เจกเจฒ เจœเจพเจ‚ เจธเจฒเฉ€เจชเจฟเฉฐเจ— 'เจคเฉ‡ เจฌเจฒเฉŒเจ• เจ•เฉ€เจคเฉ€ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจนเฉˆเฅค เจ‡เจธ เจฒเจˆ เจ†เจงเฉเจจเจฟเจ• strace เจซเจฒเจพเจˆ 'เจคเฉ‡ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจนเฉ‹ เจธเจ•เจฆเฉ‡ เจนเจจเฅค

เจ เฉฐเจขเจ• เจฆเฉ€ เจ‰เจฆเจพเจนเจฐเจจ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ:

int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    char str[] = "write men";

    write(STDOUT_FILENO, str, sizeof(str));

    /* Sleep indefinitely or until a signal arrives */
    pause();

    write(STDOUT_FILENO, str, sizeof(str));

    return EXIT_SUCCESS;
}

เจ†เจ‰ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฌเจฃเจพเจ‰ เจ…เจคเฉ‡ เจฏเจ•เฉ€เจจเฉ€ เจฌเจฃเจพเจ“ เจ•เจฟ เจ‡เจน เจœเฉฐเจฎเจฟเจ† เจนเฉ‹เจ‡เจ† เจนเฉˆ:

$ gcc examples/write-sleep.c -o write-sleep
$ ./write-sleep
./write-sleep
write me
^C
$

เจ†เจ“ เจนเฉเจฃ เจ‡เจธ เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจนเฉ‹เจฃ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเฉ€เจ:

$ ./write-sleep &
[1] 15329
write me
$ strace -p 15329
strace: Process 15329 attached
pause(
^Cstrace: Process 15329 detached
 <detached ...>

เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจ•เจพเจฒ เจฆเฉเจ†เจฐเจพ เจฌเจฒเฉŒเจ• เจ•เฉ€เจคเจพ เจ—เจฟเจ† pause. เจ†เจ“ เจฆเฉ‡เจ–เฉ€เจ เจ•เจฟ เจ‰เจน เจธเจฟเจ—เจจเจฒเจพเจ‚ 'เจคเฉ‡ เจ•เจฟเจตเฉ‡เจ‚ เจชเฉเจฐเจคเฉ€เจ•เจฟเจฐเจฟเจ† เจ•เจฐเจฆเฉ€ เจนเฉˆ:

$ strace -o write-sleep.log -p 15329 &
strace: Process 15329 attached
$
$ kill -CONT 15329
$ cat write-sleep.log
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause(
$
$ kill -TERM 15329
$ cat write-sleep.log
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
+++ killed by SIGTERM +++

เจ…เจธเฉ€เจ‚ เจซเฉเจฐเฉ€เจœเจผ เจ•เฉ€เจคเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจจเฉ‚เฉฐ เจฒเจพเจ‚เจš เจ•เฉ€เจคเจพ เจ…เจคเฉ‡ เจ‡เจธเจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจธเจผเจพเจฎเจฒ เจนเฉ‹เจ strace. เจฆเฉ‹ เจ—เฉฑเจฒเจพเจ‚ เจธเจชเฉฑเจธเจผเจŸ เจนเฉ‹ เจ—เจˆเจ†เจ‚: เจตเจฟเจฐเจพเจฎ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจนเฉˆเจ‚เจกเจฒเจฐ เจคเฉ‹เจ‚ เจฌเจฟเจจเจพเจ‚ เจธเจฟเจ—เจจเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจจเจœเจผเจฐเจ…เฉฐเจฆเจพเจœเจผ เจ•เจฐเจฆเฉ€ เจนเฉˆ เจ…เจคเฉ‡, เจตเจงเฉ‡เจฐเฉ‡ เจฆเจฟเจฒเจšเจธเจช เจ—เฉฑเจฒ เจ‡เจน เจนเฉˆ เจ•เจฟ, เจธเจŸเฉเจฐเฉˆเจธ เจฎเจพเจจเฉ€เจŸเจฐ เจจเจพ เจธเจฟเจฐเจซ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚, เจฌเจฒเจ•เจฟ เจ†เจ‰เจฃ เจตเจพเจฒเฉ‡ เจธเจฟเจ—เจจเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจตเฉ€เฅค

เจ‰เจฆเจพเจนเจฐเจจ: เจฌเจพเจฒ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจจเฉ‚เฉฐ เจŸเจฐเฉˆเจ• เจ•เจฐเจจเจพ

เจ‡เฉฑเจ• เจ•เจพเจฒ เจฆเฉเจ†เจฐเจพ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจจเจพเจฒ เจ•เฉฐเจฎ เจ•เจฐเจจเจพ fork - เจธเจพเจฐเฉ‡ เจฏเฉ‚เจจเจฟเจ•เจธ เจฆเจพ เจ†เจงเจพเจฐ. เจ†เจ‰ เจตเฉ‡เจ–เฉ€เจ เจ•เจฟ เจธเจŸเฉเจฐเฉˆเจธ เจ‡เฉฑเจ• เจธเจงเจพเจฐเจจ "เจฌเฉเจฐเฉ€เจกเจฟเฉฐเจ—" เจฆเฉ€ เจ‰เจฆเจพเจนเจฐเจฃ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจ‡เฉฑเจ• เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฆเฉ‡ เจฐเฉเฉฑเจ– เจจเจพเจฒ เจ•เจฟเจตเฉ‡เจ‚ เจ•เฉฐเจฎ เจ•เจฐเจฆเจพ เจนเฉˆ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ:

int main(int argc, char *argv[])
{
    pid_t parent_pid = getpid();
    pid_t child_pid = fork();
    if (child_pid == 0) {
        /* A child is born! */
        child_pid = getpid();

        /* In the end of the day printf is just a call to write(2). */
        printf("child (self=%d)n", child_pid);
        exit(EXIT_SUCCESS);
    }

    printf("parent (self=%d, child=%d)n", parent_pid, child_pid);

    wait(NULL);

    exit(EXIT_SUCCESS);
}

เจ‡เฉฑเจฅเฉ‡ เจฎเฉ‚เจฒ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจ‡เฉฑเจ• เจšเจพเจˆเจฒเจก เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฌเจฃเจพเจ‰เจ‚เจฆเฉ€ เจนเฉˆ, เจฆเฉ‹เจตเฉ‡เจ‚ เจธเจŸเฉˆเจ‚เจกเจฐเจก เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจจเฉ‚เฉฐ เจฒเจฟเจ–เจฆเฉ‡ เจนเจจ:

$ gcc examples/fork-write.c -o fork-write
$ ./fork-write
parent (self=11274, child=11275)
child (self=11275)

เจกเจฟเจซเฉŒเจฒเจŸ เจฐเฉ‚เจช เจตเจฟเฉฑเจš, เจ…เจธเฉ€เจ‚ เจธเจฟเจฐเจซ เจชเฉ‡เจฐเฉˆเจ‚เจŸ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจคเฉ‹เจ‚ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจฆเฉ‡เจ–เจพเจ‚เจ—เฉ‡:

$ strace -e trace=write -ofork-write.log ./fork-write
child (self=22049)
parent (self=22048, child=22049)
$ cat fork-write.log
write(1, "parent (self=22048, child=22049)"..., 33) = 33
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22049, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

เจซเจฒเฉˆเจ— เจธเจพเจฐเฉ€ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฆเฉ‡ เจฐเฉเฉฑเจ– เจจเฉ‚เฉฐ เจŸเจฐเฉˆเจ• เจ•เจฐเจจ เจตเจฟเฉฑเจš เจคเฉเจนเจพเจกเฉ€ เจฎเจฆเจฆ เจ•เจฐเจฆเจพ เจนเฉˆ -f, เจœเฉ‹ strace เจšเจพเจˆเจฒเจก เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจตเจฟเฉฑเจš เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฆเฉ€ เจจเจฟเจ—เจฐเจพเจจเฉ€ เจ•เจฐเจฆเจพ เจนเฉˆเฅค เจ‡เจน เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจฆเฉ€ เจนเจฐเฉ‡เจ• เจฒเจพเจˆเจจ เจจเฉ‚เฉฐ เจœเฉ‹เฉœเจฆเจพ เจนเฉˆ pid เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจœเฉ‹ เจธเจฟเจธเจŸเจฎ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจฌเจฃเจพเจ‰เจ‚เจฆเฉ€ เจนเฉˆ:

$ strace -f -e trace=write -ofork-write.log ./fork-write
parent (self=22710, child=22711)
child (self=22711)
$ cat fork-write.log
22710 write(1, "parent (self=22710, child=22711)"..., 33) = 33
22711 write(1, "child (self=22711)n", 19) = 19
22711 +++ exited with 0 +++
22710 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22711, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
22710 +++ exited with 0 +++

เจ‡เจธ เจธเฉฐเจฆเจฐเจญ เจตเจฟเฉฑเจš, เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฆเฉ‡ เจธเจฎเฉ‚เจน เจฆเฉเจ†เจฐเจพ เจซเจฟเจฒเจŸเจฐ เจ•เจฐเจจเจพ เจฒเจพเจญเจฆเจพเจ‡เจ• เจนเฉ‹ เจธเจ•เจฆเจพ เจนเฉˆ:

$ strace -f -e trace=%process -ofork-write.log ./fork-write
parent (self=23610, child=23611)
child (self=23611)
$ cat fork-write.log
23610 execve("./fork-write", ["./fork-write"], 0x7fff696ff720 /* 63 vars */) = 0
23610 arch_prctl(ARCH_SET_FS, 0x7f3d03ba44c0) = 0
23610 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3d03ba4790) = 23611
23610 wait4(-1,  <unfinished ...>
23611 exit_group(0)                     = ?
23611 +++ exited with 0 +++
23610 <... wait4 resumed> NULL, 0, NULL) = 23611
23610 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=23611, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
23610 exit_group(0)                     = ?
23610 +++ exited with 0 +++

เจคเจฐเฉ€เจ•เฉ‡ เจจเจพเจฒ, เจจเจตเฉ€เจ‚ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ เจ•เจฟเจนเฉœเฉ€ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เฉ€เจคเฉ€ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ?

เจ‰เจฆเจพเจนเจฐเจจ: เจนเฉˆเจ‚เจกเจฒ เจฆเฉ€ เจฌเจœเจพเจ เจซเจพเจˆเจฒ เจชเจพเจฅ

เจซเจพเจˆเจฒ เจกเจฟเจธเจ•เฉเจฐเจฟเจชเจŸเจฐเจพเจ‚ เจจเฉ‚เฉฐ เจœเจพเจฃเจจเจพ เจจเจฟเจธเจผเจšเจค เจคเฉŒเจฐ 'เจคเฉ‡ เจฒเจพเจญเจฆเจพเจ‡เจ• เจนเฉˆ, เจชเจฐ เจ–เจพเจธ เจซเจพเจˆเจฒเจพเจ‚ เจฆเฉ‡ เจจเจพเจฎ เจœเจฟเจจเฉเจนเจพเจ‚ เจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจเจ•เจธเฉˆเจธ เจ•เจฐเจฆเจพ เจนเฉˆ เจ‰เจน เจตเฉ€ เจ•เฉฐเจฎ เจตเจฟเฉฑเจš เจ† เจธเจ•เจฆเฉ‡ เจนเจจเฅค

เจ…เจ—เจฒเจพ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจ†เจฐเจœเจผเฉ€ เจซเจพเจˆเจฒ เจตเจฟเฉฑเจš เจฒเจพเจˆเจจ เจฒเจฟเจ–เจฆเจพ เจนเฉˆ:

void do_write(int out_fd)
{
    char str[] = "write me to a filen";

    if (sizeof(str) != write(out_fd, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    char tmp_filename_template[] = "/tmp/output_fileXXXXXX";

    int out_fd = mkstemp(tmp_filename_template);
    if (out_fd == -1) {
        perror("mkstemp");
        exit(EXIT_FAILURE);
    }

    do_write(out_fd);

    return EXIT_SUCCESS;
}

เจ‡เฉฑเจ• เจ†เจฎ เจ•เจพเจฒ เจฆเฉŒเจฐเจพเจจ strace เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจจเฉ‚เฉฐ เจชเจพเจธ เจ•เฉ€เจคเฉ‡ เจกเจฟเจธเจ•เฉเจฐเจฟเจชเจŸเจฐ เจจเฉฐเจฌเจฐ เจฆเจพ เจฎเฉเฉฑเจฒ เจฆเจฟเจ–เจพเจเจ—เจพ:

$ strace -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3, "write me to a filen", 20)  = 20
+++ exited with 0 +++

เจเฉฐเจกเฉ‡ เจจเจพเจฒ -y เจ‰เจชเจฏเฉ‹เจ—เจคเจพ เจซเจพเจˆเจฒ เจฆเจพ เจฎเจพเจฐเจ— เจฆเจฐเจธเจพเจ‰เจ‚เจฆเฉ€ เจนเฉˆ เจœเจฟเจธ เจจเจพเจฒ เจตเจฐเจฃเจจเจ•เจฐเจคเจพ เจ…เจจเฉเจธเจพเจฐเฉ€ เจนเฉˆ:

$ strace -y -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3</tmp/output_fileCf5MyW>, "write me to a filen", 20) = 20
+++ exited with 0 +++

เจ‰เจฆเจพเจนเจฐเจจ: เจซเจพเจˆเจฒ เจเจ•เจธเฉˆเจธ เจŸเฉเจฐเฉˆเจ•เจฟเฉฐเจ—

เจ‡เฉฑเจ• เจนเฉ‹เจฐ เจ‰เจชเจฏเฉ‹เจ—เฉ€ เจตเจฟเจธเจผเฉ‡เจธเจผเจคเจพ: เจ‡เฉฑเจ• เจ–เจพเจธ เจซเจพเจˆเจฒ เจจเจพเจฒ เจธเฉฐเจฌเฉฐเจงเจฟเจค เจธเจฟเจฐเจซ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจ•เจฐเฉ‹เฅค เจ…เจ—เจฒเจพ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจ‡เฉฑเจ• เจ†เจฐเจ—เฉ‚เจฎเฉˆเจ‚เจŸ เจฆเฉ‡ เจคเฉŒเจฐ เจคเฉ‡ เจชเจพเจธ เจ•เฉ€เจคเฉ€ เจ‡เฉฑเจ• เจ†เจฐเจฌเจฟเจŸเจฐเจฐเฉ€ เจซเจพเจˆเจฒ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจฒเจพเจˆเจจ เจœเฉ‹เฉœเจฆเจพ เจนเฉˆ:

void do_write(int out_fd)
{
    char str[] = "write me to a filen";

    if (sizeof(str) != write(out_fd, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    /*
     * Path will be provided by the first program argument.
     *  */
    const char *path = argv[1];

    /*
     * Open an existing file for writing in append mode.
     *  */
    int out_fd = open(path, O_APPEND | O_WRONLY);
    if (out_fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    do_write(out_fd);

    return EXIT_SUCCESS;
}

เจฎเฉ‚เจฒ เจฐเฉ‚เจช เจตเจฟเฉฑเจš strace เจฌเจนเฉเจค เจธเจพเจฐเฉ€ เจฌเฉ‡เจฒเฉ‹เฉœเฉ€ เจœเจพเจฃเจ•เจพเจฐเฉ€ เจฆเจฟเจ–เจพเจ‰เจ‚เจฆเจพ เจนเฉˆเฅค เจเฉฐเจกเจพ -P เจ‡เฉฑเจ• เจ†เจฐเจ—เฉ‚เจฎเฉˆเจ‚เจŸ เจฆเฉ‡ เจจเจพเจฒ เจธเจŸเจฐเฉ‡เจธ เจธเจฟเจฐเจซ เจจเจฟเจฐเจงเจพเจฐเจค เจซเจพเจˆเจฒ เจฒเจˆ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจชเฉเจฐเจฟเฉฐเจŸ เจ•เจฐเจจ เจฆเจพ เจ•เจพเจฐเจจ เจฌเจฃเจฆเจพ เจนเฉˆ:

$ strace -y -P/tmp/test_file.log -o write-file.log ./write-file /tmp/test_file.log
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = 3</tmp/test_file.log>
write(3</tmp/test_file.log>, "write me to a filen", 20) = 20
+++ exited with 0 +++

เจ‰เจฆเจพเจนเจฐเจจ: เจฎเจฒเจŸเฉ€เจฅเฉเจฐเฉˆเจกเจก เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ

เจ‰เจชเจฏเฉ‹เจ—เจคเจพ strace เจฎเจฒเจŸเฉ€-เจฅเฉเจฐเฉˆเจกเจก เจจเจพเจฒ เจ•เฉฐเจฎ เจ•เจฐเจจ เจตเฉ‡เจฒเฉ‡ เจตเฉ€ เจฎเจฆเจฆ เจ•เจฐ เจธเจ•เจฆเจพ เจนเฉˆ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ. เจจเจฟเจฎเจจเจฒเจฟเจ–เจค เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ‹ เจงเจพเจฐเจพเจตเจพเจ‚ เจคเฉ‹เจ‚ เจฎเจฟเจ†เจฐเฉ€ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจจเฉ‚เฉฐ เจฒเจฟเจ–เจฆเจพ เจนเฉˆ:

void *thread(void *arg)
{
    (void) arg;

    printf("Secondary thread: workingn");
    sleep(1);
    printf("Secondary thread: donen");

    return NULL;
}

int main(int argc, char *argv[])
{
    printf("Initial thread: launching a threadn");

    pthread_t thr;
    if (0 != pthread_create(&thr, NULL, thread, NULL)) {
        fprintf(stderr, "Initial thread: failed to create a thread");
        exit(EXIT_FAILURE);
    }

    printf("Initial thread: joining a threadn");
    if (0 != pthread_join(thr, NULL)) {
        fprintf(stderr, "Initial thread: failed to join a thread");
        exit(EXIT_FAILURE);
    };

    printf("Initial thread: done");

    exit(EXIT_SUCCESS);
}

เจ•เฉเจฆเจฐเจคเฉ€ เจคเฉŒเจฐ 'เจคเฉ‡, เจ‡เจธ เจจเฉ‚เฉฐ เจฒเจฟเฉฐเจ•เจฐ เจฒเจˆ เจ‡เฉฑเจ• เจตเจฟเจธเจผเฉ‡เจธเจผ เจจเจฎเจธเจ•เจพเจฐ เจฆเฉ‡ เจจเจพเจฒ เจ•เฉฐเจชเจพเจ‡เจฒ เจ•เฉ€เจคเจพ เจœเจพเจฃเจพ เจšเจพเจนเฉ€เจฆเจพ เจนเฉˆ - the -pthread เจซเจฒเฉˆเจ—:

$ gcc examples/thread-write.c -pthread -o thread-write
$ ./thread-write
/thread-write
Initial thread: launching a thread
Initial thread: joining a thread
Secondary thread: working
Secondary thread: done
Initial thread: done
$

เจซเจฒเฉˆเจ— -f, เจœเจฟเจตเฉ‡เจ‚ เจ•เจฟ เจจเจฟเจฏเจฎเจค เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจฆเฉ‡ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš, เจนเจฐเฉ‡เจ• เจฒเจพเจˆเจจ เจฆเฉ€ เจธเจผเฉเจฐเฉ‚เจ†เจค เจตเจฟเฉฑเจš เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจฆเฉ‡ pid เจจเฉ‚เฉฐ เจœเฉ‹เฉœ เจฆเฉ‡เจตเฉ‡เจ—เจพเฅค

เจ•เฉเจฆเจฐเจคเฉ€ เจคเฉŒเจฐ 'เจคเฉ‡, เจ…เจธเฉ€เจ‚ เจชเฉ‹เจธเจฟเจ•เจธ เจฅเฉเจฐเฉˆเจกเจธ เจธเจŸเฉˆเจ‚เจกเจฐเจก เจจเฉ‚เฉฐ เจฒเจพเจ—เฉ‚ เจ•เจฐเจจ เจฆเฉ‡ เจ…เจฐเจฅเจพเจ‚ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจฅเฉเจฐเฉˆเจก เจชเจ›เจพเจฃเจ•เจฐเจคเจพ เจฌเจพเจฐเฉ‡ เจ—เฉฑเจฒ เจจเจนเฉ€เจ‚ เจ•เจฐ เจฐเจนเฉ‡ เจนเจพเจ‚, เจชเจฐ เจฒเฉ€เจจเจ•เจธ เจตเจฟเฉฑเจš เจŸเจพเจธเจ• เจธเจผเจกเจฟเจŠเจฒเจฐ เจฆเฉเจ†เจฐเจพ เจตเจฐเจคเฉ‡ เจ—เจ เจธเฉฐเจ–เจฟเจ† เจฌเจพเจฐเฉ‡ เจ—เฉฑเจฒ เจ•เจฐ เจฐเจนเฉ‡ เจนเจพเจ‚เฅค เจฌเจพเจ…เจฆ เจฆเฉ‡ เจฆเฉเจฐเจฟเจธเจผเจŸเฉ€เจ•เฉ‹เจฃ เจคเฉ‹เจ‚, เจ‡เฉฑเจฅเฉ‡ เจ•เฉ‹เจˆ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจœเจพเจ‚ เจฅเจฐเจฟเฉฑเจก เจจเจนเฉ€เจ‚ เจนเจจ - เจ…เจœเจฟเจนเฉ‡ เจ•เจพเจฐเจœ เจนเจจ เจœเจฟเจจเฉเจนเจพเจ‚ เจจเฉ‚เฉฐ เจฎเจธเจผเฉ€เจจ เจฆเฉ‡ เจ‰เจชเจฒเจฌเจง เจ•เฉ‹เจฐเจพเจ‚ เจตเจฟเฉฑเจš เจตเฉฐเจกเจฃ เจฆเฉ€ เจœเจผเจฐเฉ‚เจฐเจค เจนเฉˆ.

เจฎเจฒเจŸเฉ€เจชเจฒ เจฅเจฐเจฟเฉฑเจกเจพเจ‚ เจตเจฟเฉฑเจš เจ•เฉฐเจฎ เจ•เจฐเจฆเฉ‡ เจธเจฎเฉ‡เจ‚, เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจฌเจนเฉเจค เจœเจผเจฟเจ†เจฆเจพ เจนเฉ‹ เจœเจพเจ‚เจฆเฉ€เจ†เจ‚ เจนเจจ:

$ strace -f -othread-write.log ./thread-write
$ wc -l thread-write.log
60 thread-write.log

เจ†เจชเจฃเฉ‡ เจ†เจช เจจเฉ‚เฉฐ เจชเฉเจฐเฉ‹เจธเฉˆเจธ เจฎเฉˆเจจเฉ‡เจœเจฎเฉˆเจ‚เจŸ เจ…เจคเฉ‡ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจคเฉฑเจ• เจนเฉ€ เจธเฉ€เจฎเจค เจ•เจฐเจจเจพ เจธเจฎเจเจฆเจพเจฐ เจนเฉˆ write:

$ strace -f -e trace="%process,write" -othread-write.log ./thread-write
$ cat thread-write.log
18211 execve("./thread-write", ["./thread-write"], 0x7ffc6b8d58f0 /* 64 vars */) = 0
18211 arch_prctl(ARCH_SET_FS, 0x7f38ea3b7740) = 0
18211 write(1, "Initial thread: launching a thre"..., 35) = 35
18211 clone(child_stack=0x7f38e9ba2fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f38e9ba39d0, tls=0x7f38e9ba3700, child_tidptr=0x7f38e9ba39d0) = 18212
18211 write(1, "Initial thread: joining a thread"..., 33) = 33
18212 write(1, "Secondary thread: workingn", 26) = 26
18212 write(1, "Secondary thread: donen", 23) = 23
18212 exit(0)                           = ?
18212 +++ exited with 0 +++
18211 write(1, "Initial thread: done", 20) = 20
18211 exit_group(0)                     = ?
18211 +++ exited with 0 +++

เจคเจฐเฉ€เจ•เฉ‡ เจจเจพเจฒ, เจธเจตเจพเจฒ. เจจเจตเจพเจ‚ เจฅเจฐเจฟเฉฑเจก เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ เจ•เจฟเจนเฉœเฉ€ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เฉ€เจคเฉ€ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ? เจฅเฉเจฐเฉˆเจกเจธ เจฒเจˆ เจ‡เจน เจ•เจพเจฒ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ†เจตเจพเจ‚ เจฒเจˆ เจ•เจพเจฒ เจคเฉ‹เจ‚ เจ•เจฟเจตเฉ‡เจ‚ เจตเฉฑเจ–เจฐเฉ€ เจนเฉˆ?

เจฎเจพเจธเจŸเจฐ เจ•เจฒเจพเจธ: เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ‡ เจธเจฎเฉ‡เจ‚ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจธเจŸเฉˆเจ•

เจนเจพเจฒ เจนเฉ€ เจตเจฟเฉฑเจš เจชเฉเจฐเจ—เจŸ เจนเฉ‹เจ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจ‡เฉฑเจ• strace เจธเจฎเจฐเฉฑเจฅเจพเจตเจพเจ‚ - เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒ เจฆเฉ‡ เจธเจฎเฉ‡เจ‚ เจซเฉฐเจ•เจธเจผเจจ เจ•เจพเจฒเจพเจ‚ เจฆเฉ‡ เจธเจŸเฉˆเจ• เจจเฉ‚เฉฐ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจ•เจฐเจจเจพเฅค เจ†เจธเจพเจจ เจ‰เจฆเจพเจนเจฐเจจ:

void do_write(void)
{
    char str[] = "write me to stdoutn";
    if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    do_write();
    return EXIT_SUCCESS;
}

เจ•เฉเจฆเจฐเจคเฉ€ เจคเฉŒเจฐ 'เจคเฉ‡, เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจฌเจนเฉเจค เจตเฉฑเจกเฉ€ เจนเฉ‹ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ, เจ…เจคเฉ‡, เจซเจฒเฉˆเจ— เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ -k (เจ•เจพเจฒ เจธเจŸเฉˆเจ• เจกเจฟเจธเจชเจฒเฉ‡เจ…), เจ‡เจน เจจเจพเจฎ เจฆเฉเจ†เจฐเจพ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจซเจฟเจฒเจŸเจฐ เจ•เจฐเจจ เจฆเจพ เจ…เจฐเจฅ เจฐเฉฑเจ–เจฆเจพ เจนเฉˆ:

$ gcc examples/write-simple.c -o write-simple
$ strace -k -e trace=write -o write-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20)  = 20
 > /lib/x86_64-linux-gnu/libc-2.27.so(__write+0x14) [0x110154]
 > /home/vkazanov/projects-my/strace-post/write-simple(do_write+0x50) [0x78a]
 > /home/vkazanov/projects-my/strace-post/write-simple(main+0x14) [0x7d1]
 > /lib/x86_64-linux-gnu/libc-2.27.so(__libc_start_main+0xe7) [0x21b97]
 > /home/vkazanov/projects-my/strace-post/write-simple(_start+0x2a) [0x65a]
+++ exited with 0 +++

เจฎเจพเจธเจŸเจฐ เจ•เจฒเจพเจธ: เจ—เจฒเจคเฉ€ เจŸเฉ€เจ•เจพ

เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจนเฉ‹เจฐ เจจเจตเฉ€เจ‚ เจ…เจคเฉ‡ เจฌเจนเฉเจค เจ‰เจชเจฏเฉ‹เจ—เฉ€ เจตเจฟเจธเจผเฉ‡เจธเจผเจคเจพ: เจ—เจฒเจคเฉ€ เจŸเฉ€เจ•เจพ. เจ‡เจฅเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ, เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจธเจŸเฉเจฐเฉ€เจฎ เจฒเจˆ เจฆเฉ‹ เจฒเจพเจˆเจจเจพเจ‚ เจฒเจฟเจ–เจฃเจพ:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void do_write(const char *str, ssize_t len)
{
    if (len != write(STDOUT_FILENO, str, (size_t)len)){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    char str1[] = "write me 1n";
    do_write(str1, sizeof(str1));

    char str2[] = "write me 2n";
    do_write(str2, sizeof(str2));

    return EXIT_SUCCESS;
}

เจ†เจ‰ เจฆเฉ‹เจจเฉ‹เจ‚ เจฒเจฟเจ–เจคเฉ€ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจŸเจฐเฉ‡เจธ เจ•เจฐเฉ€เจ:

$ gcc examples/write-twice.c -o write-twice
$ ./write-twice
write me 1
write me 2
$ strace -e trace=write -owrite-twice.log ./write-twice
write me 1
write me 2
$ cat write-twice.log
write(1, "write me 1n", 12)          = 12
write(1, "write me 2n", 12)          = 12
+++ exited with 0 +++

เจนเฉเจฃ เจ…เจธเฉ€เจ‚ เจธเจฎเฉ€เจ•เจฐเจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ injectเจ‡เฉฑเจ• เจ—เจฒเจคเฉ€ เจชเจพเจ‰เจฃ เจฒเจˆ EBADF เจธเจพเจฐเฉ€เจ†เจ‚ เจฒเจฟเจ–เจคเฉ€ เจ•เจพเจฒเจพเจ‚ เจตเจฟเฉฑเจš:

$ strace -e trace=write -e inject=write:error=EBADF -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = -1 EBADF (Bad file descriptor) (INJECTED)
+++ exited with 1 +++

เจ‡เจน เจฆเจฟเจฒเจšเจธเจช เจนเฉˆ เจ•เจฟ เจ•เจฟเจนเฉœเฉ€เจ†เจ‚ เจ—เจฒเจคเฉ€เจ†เจ‚ เจตเจพเจชเจธ เจ•เฉ€เจคเฉ€เจ†เจ‚ เจœเจพเจ‚เจฆเฉ€เจ†เจ‚ เจนเจจ เจธเจพเจฐเฉ‡ เจšเฉเจฃเฉŒเจคเฉ€เจ†เจ‚ write, เจชเฉ€เจฐ เจฆเฉ‡ เจชเจฟเฉฑเจ›เฉ‡ เจ›เฉเจชเฉ€ เจนเฉ‹เจˆ เจ•เจพเจฒ เจธเจฎเฉ‡เจคเฅค เจ‡เจน เจธเจฟเจฐเจซ เจชเจนเจฟเจฒเฉ€ เจ•เจพเจฒ เจฒเจˆ เจ‡เฉฑเจ• เจ—เจฒเจคเฉ€ เจตเจพเจชเจธ เจ•เจฐเจจ เจฒเจˆ เจธเจฎเจเจฆเจพ เจนเฉˆ:

$ strace -e trace=write -e inject=write:error=EBADF:when=1 -owrite-twice.log ./write-twice
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++

เจœเจพเจ‚ เจฆเฉ‚เจœเจพ:

$ strace -e trace=write -e inject=write:error=EBADF:when=2 -owrite-twice.log ./write-twice
write me 1
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12)          = 12
write(1, "write me 2n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++

เจ—เจฒเจคเฉ€ เจฆเฉ€ เจ•เจฟเจธเจฎ เจจเจฟเจฐเจงเจพเจฐเจค เจ•เจฐเจจเจพ เจœเจผเจฐเฉ‚เจฐเฉ€ เจจเจนเฉ€เจ‚ เจนเฉˆ:

$ strace -e trace=write -e fault=write:when=1 -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 ENOSYS (Function not implemented) (INJECTED)
write(3, "write: Function not implementedn", 32) = 32
+++ exited with 1 +++

เจนเฉ‹เจฐ เจซเจฒเฉˆเจ—เจพเจ‚ เจฆเฉ‡ เจจเจพเจฒ, เจคเฉเจธเฉ€เจ‚ เจ‡เฉฑเจ• เจ–เจพเจธ เจซเจพเจˆเจฒ เจคเฉฑเจ• เจชเจนเฉเฉฐเจš เจจเฉ‚เฉฐ "เจฌเฉเจฐเฉ‡เจ•" เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹เฅค เจ‰เจฆเจพเจนเจฐเจจ:

$ strace -y -P/tmp/test_file.log -e inject=file:error=ENOENT -o write-file.log ./write-file /tmp/test_file.log
open: No such file or directory
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = -1 ENOENT (No such file or directory) (INJECTED)
+++ exited with 1 +++

เจ—เจฒเจคเฉ€ เจ‡เฉฐเจœเฉˆเจ•เจธเจผเจจ เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, เจนเฉ‹ เจธเจ•เจฆเจพ เจนเฉˆ เจ•เจพเจฒเจพเจ‚ เจ•เจฐเจจ เจœเจพเจ‚ เจธเจฟเจ—เจจเจฒ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจ เจตเฉ‡เจฒเฉ‡ เจฆเฉ‡เจฐเฉ€ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเฉ‹เฅค

เจฌเจพเจ…เจฆ

เจ‰เจชเจฏเฉ‹เจ—เจคเจพ strace - เจ‡เฉฑเจ• เจธเจงเจพเจฐเจจ เจ…เจคเฉ‡ เจญเจฐเฉ‹เจธเฉ‡เจฎเฉฐเจฆ เจธเจพเจงเจจ. เจชเจฐ เจธเจฟเจธเจŸเจฎ เจ•เจพเจฒเจพเจ‚ เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจ…เจคเฉ‡ เจ“เจชเจฐเฉ‡เจŸเจฟเฉฐเจ— เจธเจฟเจธเจŸเจฎ เจฆเฉ‡ เจธเฉฐเจšเจพเจฒเจจ เจฆเฉ‡ เจนเฉ‹เจฐ เจชเจนเจฟเจฒเฉ‚เจ†เจ‚ เจจเฉ‚เฉฐ เจกเฉ€เจฌเฉฑเจ— เจ•เฉ€เจคเจพ เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆเฅค เจ‰เจฆเจพเจนเจฐเจจ เจฒเจˆ, เจ‡เจน เจ—เจคเฉ€เจธเจผเฉ€เจฒ เจคเฉŒเจฐ 'เจคเฉ‡ เจฒเจฟเฉฐเจ•เจก เจฒเจพเจ‡เจฌเฉเจฐเฉ‡เจฐเฉ€เจ†เจ‚ เจฒเจˆ เจ•เจพเจฒเจพเจ‚ เจจเฉ‚เฉฐ เจŸเจฐเฉˆเจ• เจ•เจฐ เจธเจ•เจฆเจพ เจนเฉˆเฅค ltrace, เจ‰เจน เจ“เจชเจฐเฉ‡เจŸเจฟเฉฐเจ— เจธเจฟเจธเจŸเจฎ เจฆเฉ‡ เจธเฉฐเจšเจพเจฒเจจ เจฆเฉ€ เจœเจพเจ‚เจš เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเจจ เจธเจฟเจธเจŸเจฎเจŸเฉˆเจช ะธ ftrace, เจ…เจคเฉ‡ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎ เจฆเฉ€ เจ•เจพเจฐเจ—เฉเจœเจผเจพเจฐเฉ€ เจฆเฉ€ เจกเฉ‚เฉฐเจ˜เจพเจˆ เจจเจพเจฒ เจœเจพเจ‚เจš เจ•เจฐเจจ เจฆเฉ€ เจ‡เจœเจพเจœเจผเจค เจฆเจฟเฉฐเจฆเจพ เจนเฉˆ เจธเฉฐเจชเฉ‚เจฐเจฃ. เจซเจฟเจฐ เจตเฉ€, เจ‡เจน เจนเฉˆ strace - เจฎเฉ‡เจฐเฉ‡ เจ†เจชเจฃเฉ‡ เจ…เจคเฉ‡ เจนเฉ‹เจฐ เจฒเฉ‹เจ•เจพเจ‚ เจฆเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ เจจเจพเจฒ เจธเจฎเฉฑเจธเจฟเจ†เจตเจพเจ‚ เจฆเฉ‡ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš เจฌเจšเจพเจ… เจฆเฉ€ เจชเจนเจฟเจฒเฉ€ เจฒเจพเจˆเจจ, เจ…เจคเฉ‡ เจฎเฉˆเจ‚ เจ‡เจธเจจเฉ‚เฉฐ เจนเจซเจผเจคเฉ‡ เจตเจฟเฉฑเจš เจ˜เฉฑเจŸเฉ‹ เจ˜เฉฑเจŸ เจฆเฉ‹ เจตเจพเจฐ เจตเจฐเจคเจฆเจพ เจนเจพเจ‚.

เจธเฉฐเจ–เฉ‡เจช เจตเจฟเฉฑเจš, เจœเฉ‡ เจคเฉเจธเฉ€เจ‚ เจฏเฉ‚เจจเจฟเจ•เจธ เจจเฉ‚เฉฐ เจชเจฟเจ†เจฐ เจ•เจฐเจฆเฉ‡ เจนเฉ‹, เจชเฉœเฉเจนเฉ‹ man 1 strace เจ…เจคเฉ‡ เจ†เจชเจฃเฉ‡ เจชเฉเจฐเฉ‹เจ—เจฐเจพเจฎเจพเจ‚ 'เจคเฉ‡ เจเจพเจค เจฎเจพเจฐเจจ เจฒเจˆ เจธเฉเจคเฉฐเจคเจฐ เจฎเจนเจฟเจธเฉ‚เจธ เจ•เจฐเฉ‹!

เจธเจฐเฉ‹เจค: www.habr.com

เจ‡เฉฑเจ• เจŸเจฟเฉฑเจชเจฃเฉ€ เจœเฉ‹เฉœเฉ‹