[ Team LiB ] Previous Section Next Section

C.1 System Call Tracing

Many versions of Unix provide a system call tracing facility. This can often provide a valuable debugging technique.

Working at this level, we need to differentiate between a system call and a function. The former is an entry point into the kernel, and that is what we are able to trace with the tools we will look at in this section. POSIX and most other standards use the term "function" to describe what appears to the user to be functions, even though on some implementations, they may be system calls. For example, on a Berkeley-derived kernel, socket is a system call even though it appears to be a normal C function to the application programmer. But under SVR4, we will see shortly that it is a library function in the sockets library that issues calls to putmsg and getmsg, these latter two being actual system calls.

In this section, we will examine the system calls involved in running our daytime client. We showed this client in Figure 1.5.

BSD Kernel Sockets

We start with FreeBSD, a Berkeley-derived kernel in which all the socket functions are system calls. The ktrace program is provided by FreeBSD to run a program and trace the system calls that are executed. This writes the trace information to a file (whose default name is ktrace.out), which we print with kdump. We execute our sockets client as


freebsd % ktrace daytimetcpcli 192.168.42.2
Tue Aug 19 23:35:10 2003

We then execute kdump to output the trace information to standard output.


 3211 daytimetcpcli CALL socket(0x2,0x1,0)
 3211 daytimetcpcli RET  socket 3

 3211 daytimetcpcli CALL connect(0x3,0x7fdffffe820,0x10)
 3211 daytimetcpcli RET  connect 0

 3211 daytimetcpcli CALL read(0x3,0x7fdffffe830,0x1000)
 3211 daytimetcpcli GIO  fd 3 read 26 bytes
      "Tue Aug 19 23:35:10 2003
      "
 3211 daytimetcpcli RET  read 26/0x1a

...

 3211 daytimetcpcli CALL write(0x1,0x204000,0x1a)
 3211 daytimetcpcli GIO  fd 1 wrote 26 bytes
      "Tue Aug 19 23:35:10 2003/r
      "
 3211 daytimetcpcli RET  write 26/0x1a

 3211 daytimetcpcli CALL read(0x3,0x7fdffffe830,0x1000)
 3211 daytimetcpcli GIO  fd 3 read 0 bytes
      ""
 3211 daytimetcpcli RET  read 0

 3211 daytimetcpcli CALL exit(0)

3211 is the PID. CALL identifies a system call, RET is the return, and GIO stands for generic process I/O. We see the calls to socket and connect, followed by the call to read that returns 26 bytes. Our client writes these bytes to standard output and the next call to read returns 0 (EOF).

Solaris 9 Kernel Sockets

Solaris 2.x is based on SVR4 and all the releases before 2.6 have implemented sockets as shown in Figure 31.3. One problem, however, with all SVR4 implementations that implement sockets in this fashion is that they rarely provide 100% compatibility with Berkeley-derived kernel sockets. To provide additional compatibility, versions starting with Solaris 2.6 changed the implementation technique and implemented sockets using a sockfs filesystem. This provides kernel sockets, as we can verify using truss on our sockets client.


solaris % truss -v connect daytimetcpcli 127.0.0.1
Mon Sep  8 12:16:42 2003

After the normal library linking, the first system call we see is to so_socket, a system call invoked by our call to socket.


so_socket(PF_INET, SOCK_STREAM, IPPROTO_IP, "", 1) = 3
connect(3, 0xFFBFDEF0, 16, 1)                   =0
        AF_INET  name = 127.0.0.1  port = 13
read(3, " M o n   S e p     8   1".., 4096)     = 26
Mon Sep  8 12:48:06 2003
write(1, " M o n   S e p     8   1".., 26)      = 26
read(3, 0xFFBFDF03, 4096)                       = 0
_exit(0)

The first three arguments to so_socket are our three arguments to socket.

We see that connect is a system call, and truss, when invoked with the -v connect flag, prints the contents of the socket address structure pointed to by the second argument (the IP address and port number). The only system calls that we have replaced with ellipses are a few dealing with standard input and standard output.

    [ Team LiB ] Previous Section Next Section