Strace ho Linux: nalane, moralo le ts'ebeliso

Strace ho Linux: nalane, moralo le ts'ebeliso

Lits'ebetsong tse tšoanang le tsa Unix, puisano ea lenaneo le lefats'e le kantle le sistimi ea ts'ebetso e etsahala ka sete e nyane ea mesebetsi - mehala ea sistimi. Sena se bolela hore molemong oa ho lokisa liphoso ho ka ba molemo ho hloela mehala ea sistimi e etsoang ke lits'ebetso.

Sesebelisoa se u thusa ho beha leihlo "bophelo ba haufi" ba mananeo a Linux strace, e leng taba eo ho buuoang ka eona sehloohong sena. Mehlala ea tšebeliso ea thepa ea lihloela e tsamaisana le histori e khutšoanyane strace le tlhaloso ea moralo oa mananeo a joalo.

Tse ka hare

Tšimoloho ea mefuta

Sehokelo sa mantlha lipakeng tsa mananeo le OS kernel ho Unix ke mehala ea sistimi. mehala ea tsamaiso, syscalls), tšebelisano ea mananeo le lefats'e le kantle e etsahala ka tsona feela.

Empa phetolelong ea pele ea sechaba ea Unix (Mofuta oa 6 Unix, 1975) ho ne ho se na mekhoa e bonolo ea ho latela boitšoaro ba lits'ebetso tsa basebelisi. Ho rarolla bothata bona, Bell Labs e tla ntlafatsa mofuta o latelang (Mofuta oa 7 Unix, 1979) o ile a etsa tlhahiso ea pitso e ncha ea tsamaiso - ptrace.

ptrace e ile ea ntlafatsoa haholo-holo bakeng sa li-debugger tse sebetsanang, empa qetellong ea lilemo tsa bo-80 (nakong ea khoebo. Sistimi ea V Phallo ea 4) motheong ona, li-debugger tse neng li sa tsepamise kelello—li-system call tracers—li ile tsa hlaha ’me tsa sebelisoa haholo.

Ea pele mofuta o tšoanang oa strace o ile oa hatisoa ke Paul Cronenburg lethathamong la mangolo la comp.sources.sun ka 1992 e le mokhoa o mong oa ts'ebeliso e koetsoeng. trace ho tloha ho Letsatsi. Ka bobeli clone le tsa mantlha li ne li reretsoe SunOS, empa ka 1994 strace e ile ea fetisetsoa ho System V, Solaris le Linux e ntseng e tsoela pele ho tsebahala.

Kajeno strace e tšehetsa Linux feela 'me e itšetlehile ka eona ptrace, e nang le likeketso tse ngata.

Mohlokomeli oa sejoale-joale (le ea mafolofolo haholo). strace - Dmitry Levin. Ka lebaka la hae, ts'ebeliso e ile ea fumana likarolo tse tsoetseng pele joalo ka ente ea phoso mehala ea sistimi, ts'ehetso ea meralo e mengata ea meralo, 'me haholo-holo, mascot. Mehloli e seng molaong e bolela hore khetho e ile ea oela holim'a mpshe ka lebaka la ho lumellana pakeng tsa lentsoe la Serussia "mpshe" le lentsoe la Senyesemane "strace".

Ho bohlokoa hape hore mohala oa sistimi ea ptrace le li-tracer ha lia ka tsa kenyelletsoa ho POSIX, leha ho na le nalane e telele le ts'ebetsong Linux, FreeBSD, OpenBSD le Unix ea setso.

Strace sesebelisoa ka bokhutšoanyane: Piglet Trace

"Ha ua lebelloa ho utloisisa sena" (Dennis Ritchie, fana ka maikutlo ho Version 6 khoutu ea mohloli oa Unix)

Ho tloha bongoaneng, ha ke khone ho ema mabokose a matšo: ha kea ka ka bapala ka lipapali, empa ke ile ka leka ho utloisisa sebopeho sa bona (batho ba baholo ba ne ba sebelisa lentsoe "ho robeha," empa u se ke ua lumela maleme a khopo). Mohlomong ke ka lebaka lena moetlo o sa reroang oa Unix oa pele le mokhatlo oa sejoale-joale o bulehileng o haufi haholo le nna.

Bakeng sa merero ea sehlooho sena, ha ho utloahale ho qhaqha khoutu ea mohloli oa strace, e seng e hōlile ka lilemo tse mashome. Empa ha hoa lokela ho ba le liphiri tse setseng bakeng sa babali. Ka hona, ho bonts'a molao-motheo oa ts'ebetso ea mananeo a joalo a marang-rang, ke tla fana ka khoutu bakeng sa tracer e nyane - Piglet Trace (ptr). Ha e tsebe ho etsa ntho leha e le efe e khethehileng, empa ntho e ka sehloohong ke mehala ea tsamaiso ea lenaneo - e hlahisa:

$ 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

Piglet Trace e hlokomela makholo a mehala ea sistimi ea Linux (bona. tafoleng) mme e sebetsa feela ho meralo ea x86-64. Sena se lekane bakeng sa merero ea thuto.

Ha re shebeng mosebetsi oa clone ea rona. Tabeng ea Linux, li-debugger le li-tracers li sebelisa, joalokaha ho boletsoe ka holimo, mohala oa tsamaiso ea ptrace. E sebetsa ka ho fetisa khang ea pele li-identifiers tsa litaelo, tseo re li hlokang feela PTRACE_TRACEME, PTRACE_SYSCALL и PTRACE_GETREGS.

Tracer e qala ka mokhoa o tloaelehileng oa Unix: fork(2) e qala ts'ebetso ea ngoana, eo le eona e sebelisang exec(3) e qala lenaneo le ntseng le ithutoa. Ntho feela e poteletseng mona ke phephetso ptrace(PTRACE_TRACEME) pele exec: Ts'ebetso ea ngoana e lebelletse hore ts'ebetso ea motsoali e tla e beha leihlo:

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");
}

Ts'ebetso ea motsoali joale e lokela ho letsetsa wait(2) ts'ebetsong ea ngoana, ke hore, etsa bonnete ba hore ho fetohela ho trace mode ho etsahetse:

/* 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");

Mothating ona, litokisetso li felile 'me u ka tsoela pele ka kotloloho ho latedisa mehala ea sistimi ka loop e sa feleng.

Bothata ptrace(PTRACE_SYSCALL) e tiisa hore ho latela wait motsoali o tla qeta pele mohala oa sistimi o etsoa kapa hang ka mor'a hore o phethe. Pakeng tsa mehala e 'meli u ka etsa ketso efe kapa efe: fetola mohala ka o mong, fetola likhang kapa boleng ba ho khutlisa.

Re hloka feela ho bitsa taelo habeli ptrace(PTRACE_GETREGS)ho fumana boemo ba ngoliso rax pele ho mohala (nomoro ea mohala oa sistimi) le hang kamora (boleng ba ho khutlisa).

Ha e le hantle, potoloho:

/* 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);
}

Ke eona tracer kaofela. Joale ua tseba hore na u ka qala ho tsamaisa thepa e latelang hokae DTrace ho Linux.

Lintlha tsa motheo: ho tsamaisa lenaneo le tsamaisang strace

E le mokhoa oa pele oa tšebeliso strace, mohlomong ho bohlokoa ho qotsa mokhoa o bonolo - ho qala ts'ebeliso e sebetsang strace.

E le hore re se ke ra kenella ka har'a lethathamo le sa feleng la mehala ea lenaneo le tloaelehileng, rea ngola bonyane lenaneo ho potoloha 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;
}

Ha re theheng lenaneo mme re netefatse hore le ea sebetsa:

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

'Me qetellong, a re e tsamaise tlas'a taolo ea strace:

$ 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)                           = ?

"Mantsoe" haholo ebile ha a rutehe haholo. Ho na le mathata a mabeli mona: tlhahiso ea lenaneo e kopantsoe le tlhahiso strace le mehala e mengata ea tsamaiso e sa re rateng.

U ka arola phallo e tloaelehileng ea lenaneo le tlhahiso ea phoso ea strace u sebelisa -o switch, e tsamaisang lethathamo la mehala ea sistimi ho faele ea likhang.

E sala e le ho sebetsana le bothata ba li-call tse "eketsehileng". Ha re nke hore re thahasella mehala feela write. Senotlolo -e e o lumella ho hlakisa mantsoe ao mehala ea sistimi e tla sefuoa. Khetho e tsebahalang haholo ea maemo ke, ka tlhaho, trace=*, eo ka eona u ka sieang mehala feela e re khahlang.

Ha e sebelisoa ka nako e le 'ngoe -o и -e re tla fumana:

$ 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 +++

Kahoo, ua bona, ho bonolo haholo ho e bala.

U ka boela ua tlosa mehala ea sistimi, mohlala, e amanang le kabo ea memori le ho lokolla:

$ 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 +++

Ela hloko lets'oao le phonyohileng lethathamong la mehala e sa kenyelletsoeng: sena se hlokoa ke khetla ea taelo. khetla).

Phetolelong ea ka ea glibc, mohala oa sistimi o emisa ts'ebetso exit_group, eseng setso _exit. Bona ke bothata ba ho sebetsa ka mehala ea sistimi: sebopeho seo moetsi oa lenaneo a sebetsang ka sona ha se amane ka kotloloho le mehala ea sistimi. Ho feta moo, e fetoha kamehla ho itšetlehile ka ts'ebetsong le sethaleng.

Lintlha tsa motheo: ho kopanya mokhoa oa ho fofa

Qalong, tsamaiso ea ptrace e bitsa moo e hahiloeng teng strace, e ka sebelisoa feela ha ho tsamaisoa lenaneo ka mokhoa o khethehileng. Moeli ona o ne o ka utloahala o utloahala mehleng ea Version 6 Unix. Matsatsing ana, sena ha se sa lekana: ka linako tse ling ho hlokahala hore u batlisise mathata a lenaneo le sebetsang. Mohlala o tloaelehileng ke ts'ebetso e koetsoeng ka letsoho kapa ho robala. Ka hona kajeno strace e ka kopanya lits'ebetso ha e fofa.

Mohlala oa serame mananeo a:

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;
}

Ha re theheng lenaneo mme re netefatse hore le hoamme:

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

Joale ha re lekeng ho e kopanya:

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

Lenaneo le koetsoe ke mohala pause. A re boneng hore na o itšoara joang ka lipontšo:

$ 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 +++

Re ile ra qala lenaneo le hatselitsoeng mme ra le kopanya re sebelisa strace. Lintho tse peli li ile tsa hlaka: mohala oa khefutso o iphapanyetsa matšoao ntle le batho ba sebetsang, 'me, ho khahlisang le ho feta, li-monitor tsa strace ha se mehala ea sistimi feela, empa le matšoao a kenang.

Mohlala: Ho Latela Mekhoa ea Bana

Ho sebetsa le lits'ebetso ka mohala fork - motheo oa li-Unixes tsohle. Ha re boneng hore na strace e sebetsa joang le sefate sa ts'ebetso re sebelisa mohlala oa "ho ikatisa" mananeo a:

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);
}

Mona ts'ebetso ea mantlha e theha ts'ebetso ea ngoana, ka bobeli e ngolla tlhahiso e tloaelehileng:

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

Ka kamehla, re tla bona feela mehala ea sistimi ho tsoa ts'ebetsong ea motsoali:

$ 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 +++

Folakha e u thusa ho latela sefate sa ts'ebetso eohle -f, eo strace e lekola mehala ea sistimi ts'ebetsong ea bana. Sena se eketsa moleng o mong le o mong oa tlhahiso pid tshebetso e etsang tlhahiso ea tsamaiso:

$ 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 +++

Moelelong ona, ho sefa ka sehlopha sa mehala ea sistimi ho ka ba molemo:

$ 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 +++

Ka tsela, ke mohala ofe oa tsamaiso o sebelisetsoang ho theha mokhoa o mocha?

Mohlala: litsela tsa lifaele ho e-na le li-handle

Ho tseba litlhaloso tsa lifaele ho hlile ho molemo, empa mabitso a lifaele tse khethehileng tseo lenaneo le li fihlelang le tsona li ka ba molemo.

E latelang lenaneo e ngola mola ho faele ea nakoana:

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;
}

Ka nako ya call e tlwaelehileng strace e tla bonts'a boleng ba nomoro e hlalosang e fetiselitsoeng mohala oa sistimi:

$ 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 +++

Ka folakha -y Sesebelisoa se bonts'a tsela e eang faeleng eo descriptor e lumellanang le eona:

$ 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 +++

Mohlala: Ho Tracking File Access

Karolo e 'ngoe ea bohlokoa: bonts'a feela mehala ea sistimi e amanang le faele e itseng. E 'ngoe lenaneo e hlomathisa mola faeleng e seng molaong e fetisitsoeng joalo ka khang:

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;
}

ke default strace e bonts'a lintlha tse ngata tse sa hlokahaleng. Folakha -P ka khang e etsa hore strace e hatise mehala feela ho faele e boletsoeng:

$ 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 +++

Mohlala: Mananeo a Multithreaded

Tšebeliso strace e ka boela ea thusa ha e sebetsa ka likhoele tse ngata lenaneo. Lenaneo le latelang le ngolla tlhahiso e tloaelehileng ho tsoa melapong e 'meli:

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);
}

Ka tlhaho, e tlameha ho bokelloa ka tumeliso e khethehileng ho sehokelo - the -pthread flag:

$ 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
$

Senya -f, joalo ka tabeng ea mekhoa e tloaelehileng, e tla eketsa pid ea ts'ebetso qalong ea mola o mong le o mong.

Ka tlhaho, ha re bue ka sekhetho sa likhoele ka kutloisiso ea ts'ebetsong ea maemo a POSIX Threads, empa ka palo e sebelisoang ke kemiso ea mosebetsi ho Linux. Ho ea ka pono ea morao-rao, ha ho na mekhoa kapa likhoele - ho na le mesebetsi e lokelang ho ajoa har'a li-cores tse teng tsa mochine.

Ha o sebetsa ka likhoele tse ngata, mehala ea sistimi e ba ngata haholo:

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

Hoa utloahala ho ipehela meeli ea ho sebetsana le tsamaiso le mehala ea sistimi feela 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 +++

Ka tsela, lipotso. Ke mohala ofe oa sistimi o sebelisoang ho theha khoele e ncha? Pitso ee ea likhoele e fapana joang le pitso ea lits'ebetso?

Sehlopha sa Master: process stack ka nako ea mohala oa sistimi

E 'ngoe ea tse sa tsoa hlaha strace bokhoni - e bonts'a pokello ea mehala ea ts'ebetso ka nako ea mohala oa sistimi. E bonolo mohlala:

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;
}

Ka tlhaho, tlhahiso ea lenaneo e fetoha haholo voluminous, 'me, ho phaella ho folakha -k (call stack display), hoa utloahala ho sefa mehala ea sistimi ka mabitso:

$ 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 +++

Sehlopha sa Master: ente ea phoso

Le tšobotsi e 'ngoe e ncha le e sebetsang haholo: ente ea liphoso. Mona lenaneo, ho ngola mela e 'meli ho molatsoana oa tlhahiso:

#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;
}

Ha re latele mehala ka bobeli:

$ 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 +++

Hona joale re sebelisa lentsoe injectho kenya phoso EBADF ka li-call tsohle tse ngoloang:

$ 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 +++

Hoa thahasellisa hore na ho khutlisetsoa liphoso life tsohle mathata write, ho kenyelletsa le mohala o patiloeng ka mor'a tšabo. Hoa utloahala ho khutlisa phoso bakeng sa mohala oa pele:

$ 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 +++

Kapa ea bobeli:

$ 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 +++

Ha ho hlokahale ho hlakisa mofuta oa phoso:

$ 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 +++

Hammoho le lifolakha tse ling, u ka "senya" ho fihlella faele e itseng. Mohlala:

$ 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 +++

Ntle le ente ea phoso, ka hlahisa tieho ha o letsa kapa o amohela matshwao.

Afterword

Tšebeliso strace - sesebelisoa se bonolo le se ka tšeptjoang. Empa ntle le mehala ea sistimi, likarolo tse ling tsa ts'ebetso ea mananeo le sistimi ea ts'ebetso li ka senyeha. Mohlala, e ka latella mehala ho lilaebraring tse hokahaneng ka matla. ltrace, ba ka sheba ts'ebetso ea sistimi e sebetsang SystemTap и frace, 'me e u lumella ho batlisisa ka botebo ts'ebetso ea lenaneo sehlahisoa. Leha ho le joalo, ho joalo strace - mohala oa pele oa ts'ireletso haeba ho na le mathata ka mananeo a ka le a batho ba bang, 'me ke e sebelisa bonyane makhetlo a' maloa ka beke.

Ka bokhutšoanyane, haeba u rata Unix, bala man 1 strace 'me u ikutloe u lokolohile ho sheba mananeo a hau!

Source: www.habr.com

Eketsa ka tlhaloso