List of Questions
*****************
1. Process Control
1.1 Creating new processes: fork()
1.1.1 What does fork() do?
1.1.2 What's the difference between fork() and vfork()?
1.1.3 Why use _exit rather than exit in the child branch of a fork?
1.2 Environment variables
1.2.1 How can I get/set an environment variable from a program?
1.2.2 How can I read the whole environment?
1.3 How can I sleep for less than a second?
1.4 How can I get a finer-grained version of alarm()?
1.5 How can a parent and child process communicate?
1.6 How do I get rid of zombie processes?
1.6.1 What is a zombie?
1.6.2 How do I prevent them from occuring?
1.7 How do I get my program to act like a daemon?
1.8 How can I look at process in the system like ps does?
1.9 Given a pid, how can I tell if it's a running program?
1.10 What's the return value of system/pclose/waitpid?
1.11 How do I find out about a process' memory usage?
1.12 Why do processes never decrease in size?
1.13 How do I change the name of my program (as seen by `ps')?
1.14 How can I find a process' executable file?
1.14.1 So where do I put my configuration files then?
1.15 Why doesn't my process get SIGHUP when its parent dies?
1.16 How can I kill all descendents of a process?
2. General File handling (including pipes and sockets)
2.1 How to manage multiple connections?
2.1.1 How do I use select()?
2.1.2 How do I use poll()?
2.1.3 Can I use SysV IPC at the same time as select or poll?
2.2 How can I tell when the other end of a connection shuts down?
2.3 Best way to read directories?
2.4 How can I find out if someone else has a file open?
2.5 How do I `lock' a file?
2.6 How do I find out if a file has been updated by another process?
2.7 How does the `du' utility work?
2.8 How do I find the size of a file?
2.9 How do I expand `~' in a filename like the shell does?
2.10 What can I do with named pipes (FIFOs)?
2.10.1 What is a named pipe?
2.10.2 How do I create a named pipe?
2.10.3 How do I use a named pipe?
2.10.4 Can I use a named pipe across NFS?
2.10.5 Can multiple processes write to the pipe simultaneously?
2.10.6 Using named pipes in applications
3. Terminal I/O
3.1 How can I make my program not echo input?
3.2 How can I read single characters from the terminal?
3.3 How can I check and see if a key was pressed?
3.4 How can I move the cursor around the screen?
3.5 What are pttys?
3.6 How to handle a serial port or modem?
3.6.1 Serial device names and types
3.6.2 Setting up termios flags
3.6.2.1 c_iflag
3.6.2.2 c_oflag
3.6.2.3 c_cflag
3.6.2.4 c_lflag
3.6.2.5 c_cc
4. System Information
4.1 How can I tell how much memory my system has?
4.2 How do I check a user's password?
4.2.1 How do I get a user's password?
4.2.2 How do I get shadow passwords by uid?
4.2.3 How do I verify a user's password?
5. Miscellaneous programming
5.1 How do I compare strings using wildcards?
5.1.1 How do I compare strings using filename patterns?
5.1.2 How do I compare strings using regular expressions?
5.2 What's the best way to send mail from a program?
5.2.1 The simple method: /bin/mail
5.2.2 Invoking the MTA directly: /usr/lib/sendmail
5.2.2.1 Supplying the envelope explicitly
5.2.2.2 Allowing sendmail to deduce the recipients
6. Use of tools
6.1 How can I debug the children after a fork?
6.2 How to build library from other libraries?
6.3 How to create shared libraries / dlls?
6.4 Can I replace objects in a shared library?
6.5 How can I generate a stack dump from within a running program?
1. Process Control
******************
1.1 Creating new processes: fork()
==================================
1.1.1 What does fork() do?
--------------------------
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
The `fork()' function is used to create a new process from an existing
process. The new process is called the child process, and the existing
process is called the parent. You can tell which is which by checking the
return value from `fork()'. The parent gets the child's pid returned to
him, but the child gets 0 returned to him. Thus this simple code
illustrate's the basics of it.
pid_t pid;
switch (pid = fork())
{
case -1:
/* Here pid is -1, the fork failed */
/* Some possible reasons are that you're */
/* out of process slots or virtual memory */
perror("The fork failed!");
break;
case 0:
/* pid of zero is the child */
/* Here we're the child...what should we do? */
/* ... */
/* but after doing it, we should do something like: */
_exit(0);
default:
/* pid greater than zero is parent getting the child's pid */
printf("Child's pid is %d\n",pid);
}
Of course, one can use `if()... else...' instead of `switch()', but the
above form is a useful idiom.
Of help when doing this is knowing just what is and is not inherited by the
child. This list can vary depending on Unix implementation, so take it
with a grain of salt. Note that the child gets *copies* of these things,
not the real thing.
Inherited by the child from the parent:
* process credentials (real/effective/saved UIDs and GIDs)
* environment
* stack
* memory
* open file descriptors (note that the underlying file positions are
shared between the parent and child, which can be confusing)
* close-on-exec flags
* signal handling settings
* nice value
* scheduler class
* process group ID
* session ID
* current working directory
* root directory
* file mode creation mask (umask)
* resource limits
* controlling terminal
Unique to the child:
* process ID
* different parent process ID
* Own copy of file descriptors and directory streams.
* process, text, data and other memory locks are NOT inherited.
* process times, in the tms struct
* resource utilizations are set to 0
* pending signals initialized to the empty set
* timers created by timer_create not inherited
* asynchronous input or output operations not inherited
1.1.2 What's the difference between fork() and vfork()?
-------------------------------------------------------
Some systems have a system call `vfork()', which was originally designed as
a lower-overhead version of `fork()'. Since `fork()' involved copying the
entire address space of the process, and was therefore quite expensive, the
`vfork()' function was introduced (in 3.0BSD).
*However*, since `vfork()' was introduced, the implementation of `fork()'
has improved drastically, most notably with the introduction of
`copy-on-write', where the copying of the process address space is
transparently faked by allowing both processes to refer to the same
physical memory until either of them modify it. This largely removes the
justification for `vfork()'; indeed, a large proportion of systems now lack
the original functionality of `vfork()' completely. For compatibility,
though, there may still be a `vfork()' call present, that simply calls
`fork()' without attempting to emulate all of the `vfork()' semantics.
As a result, it is *very* unwise to actually make use of any of the
differences between `fork()' and `vfork()'. Indeed, it is probably unwise
to use `vfork()' at all, unless you know exactly *why* you want to.
The basic difference between the two is that when a new process is created
with `vfork()', the parent process is temporarily suspended, and the child
process might borrow the parent's address space. This strange state of