Book Excerpt
Linux Processes: Structure, Hangs and Core Dumps
Efficient and effective resolution practices
Jul. 13, 2006 04:30 PM
Now that the trace is running in window two, we need to issue the ll command in window one.
3. Window one: Issue the ll command.
# ll test
rw-r--r-- 1 chris chris 46759 Sep 7 21:53 test
4. Window two: Here are the results of the stdout and stopping the trace.
# strace -o /tmp/ll.strace -f -p 16935
Process 16935 attached <-- Trace running on 16935
Process 17424 attached <-- forked child process
Process 17424 detached <-- child ending returning to parent
Process 16935 detached <-- ctrl +c ending trace
The trace shows the fork() and execve() calls. Note that
we are not showing the entire trace because so many system calls take
place for each seemingly simple command.
...
16935 fork() = 17424 <-- NEW task's PID
17424 --- SIGSTOP (Stopped (signal)) @ 0 (0) ---
17424 getpid() = 17424
17424 rt_sigprocmask(SIG_SETMASK, [RTMIN], NULL, 8) = 0
17424 rt_sigaction(SIGTSTP, {SIG_DFL}, {SIG_IGN}, 8) = 0
17424 rt_sigaction(SIGTTIN, {SIG_DFL}, {SIG_IGN}, 8) = 0
17424 rt_sigaction(SIGTTOU, {SIG_DFL}, {SIG_IGN}, 8) = 0
17424 setpgid(17424, 17424) = 0
17424 rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [RTMIN], 8) = 0
17424 ioctl(255, TIOCSPGRP, [17424]) = 0
17424 rt_sigprocmask(SIG_SETMASK, [RTMIN], NULL, 8) = 0
17424 rt_sigaction(SIGINT, {SIG_DFL}, {0x8087030, [], SA_RESTORER, \ 0x4005aca8}, 8) = 0
17424 rt_sigaction(SIGQUIT, {SIG_DFL}, {SIG_IGN}, 8) = 0
17424 rt_sigaction(SIGTERM, {SIG_DFL}, {SIG_IGN}, 8) = 0
17424 rt_sigaction(SIGCHLD, {SIG_DFL}, {0x80776a0, [], SA_RESTORER, \ 0x4005aca8}, 8) = 0
17424 execve("/bin/ls", ["ls", "-F", "--color=auto", "-l", "test"], \
[/* 56 vars */]) = 0
Summary of Process Creation
The fork() call creates a new
task and assigns a PID, and this step is soon followed by the execve()
call, executing the command along with its arguments. In this case, we
see that the ll test command is actually ls -F --color=auto -l test.
Linux Process Termination
An understanding of process
termination is useful for troubleshooting a process. As with process
creation, the termination or exiting of a process is like that of any
other UNIX flavor. If signal handling is implemented, the parent can be
notified when its children terminate irregularly. Additionally, the
parent process can also wait for the child to exit with some variation
of wait(). When a process terminates or calls exit(), it returns its
exit code to the caller (parent). At this point, the process is in a
zombie or defunct state, waiting for the parent to reap the process. In
some cases, the parent has long since died before the child. In these
cases, the child has become orphaned, at which point init becomes the
parent, and the return codes of the process are passed to init.
Linux Threads
No discussion of process
fundamentals is complete without an explanation of Linux threads
because an understanding of threads is crucial for troubleshooting
processes. As mentioned earlier, the implementation of threads in Linux
differs from that of UNIX because Linux threads are not contained
within the proc structure. However, Linux does support multithreaded
applications. "Multithreading" just means two or more threads working
in parallel with each other while sharing the same address space.
Multithreaded applications in Linux just use more than one task.
Following this logic in the source, include/linux/sched.h shows that
the task_struct structure maintains a one-to-one relationship with the
task's thread through the use of a pointer to the thread_info
structure, and this structure just points back to the task structure.
Excerpts from the source illustrate the one-to-one relationship between a Linux task and thread.
include/linux/sched.h
...
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
struct thread_info *thread_info;
...
To see the thread_info structure point back to the task, we review include/asm-i386/thread_info.h.
...
struct thread_info {
struct task_struct *task; /* main task structure */
...
About James KirklandJames Kirkland is a Senior Consultant for Racemi. He was previously a senior systems administrator at Hewlett-Packard. He has been working with Unix variants for more than 10 years. James is a Red Hat Certified engineer, Linux LPIC level one certified, and an HP-UX certified system administrator. He has been working with Linux for seven years and HP-UX for eight years. He has been a participant at HP World, LinuxWorld, and numerous internal HP forums.
About David CarmichaelDavid Carmichael works for Hewlett-Packard as a technical problem manager in Alpharetta, Georgia. He earned a bachelors degree in computer science from West Virginia University in 1987 and has been helping customers resolve their IT problems ever since. David has written articles for HP's IT Resource Center (http://itrc.hp.com) and presented at HP World 2003.
About Greg TinkerGreg Tinker began his career while at Bellsouth in Atlanta, Georgia. Greg joined Hewlett-Packard in 1999. Greg's primary role is as a storage business recovery specialist and has participated in HP World, taught several classes in Unix/Linux and Disk Array technology, and obtained various certifications including certifications in Advanced Clusters, SAN, and Linux.
About Chris TinkerChris Tinker began his career in computers while working as a Unix System Administrator for Lockheed Martin in Marietta, Georgia. Chris joined Hewlett-Packard in 1999. Chris's primary role at HP is as a senior software business recovery specialist and has participated in HP World, taught several classes in Unix/Linux and Disk Array technology, and obtained various certifications including certifications in Advanced Clusters, SAN, and Linux.