Search in shivacherukuri.tech@blogger.com

Sunday, April 25, 2010

Unix programming Faq

Unix Programming FAQ (v1.37)

There are reader questions on this topic!
Help others by sharing your knowledge

From: Andrew Gierth <andrew@erlenstar.demon.co.uk>
Newsgroups: comp.unix.programmer
Subject: Unix Programming FAQ (v1.37)
Date: 23 Oct 2003 19:40:02 +0100
Message-ID: <auto-cup-faq-000136-20031023194001@erlenstar.demon.co.uk>
Summary: This posting contains answers to frequently-asked questions regarding
programming in the Unix environment.
Keywords: unix faq
X-Post-Filter: postfilter v0.6 alpha

Archive-Name: unix-faq/programmer/faq
Comp-unix-programmer-Archive-Name: faq
URL: http://www.erlenstar.demon.co.uk/unix/faq_toc.html
URL: http://www.whitefang.com/unix/faq_toc.html
Posting-Frequency: every 2 weeks
Copyright: Collection Copyright (C) 1997-2000 Andrew Gierth.
Last-Modified: 2000/09/01 06:34:57
Version: 1.37

==============================================================================

About this FAQ
**************

$Id: rawfaq.texi,v 1.37 2000/09/01 06:34:57 andrew Exp $

This FAQ was originally begun by Patrick Horgan in May 1996; I took it over
after it had been lying idle for several months. I've reorganised it a bit
and added some stuff; I still regard it as `under development'.

Comments, suggestions, additions, corrections etc. should be sent to the
maintainer at: <andrew@erlenstar.demon.co.uk>.

A hypertext version of this document is available on the WWW. The home site
is located at `http://www.erlenstar.demon.co.uk/unix/faq_toc.html'. A US
mirror site is available at `http://www.whitefang.com/unix/faq_toc.html'.

This document is available by FTP from the news.answers archives at
rtfm.mit.edu and its many mirror sites worldwide. The official archive name
is `unix-faq/programmer/faq'. Sites which also archive *.answers posts by
group should also carry the file under the `comp.unix.programmer' directory.

Other sources of information are not listed here. You can find pointers to
other FAQs, books, source code etc. in the regular [READ ME FIRST] posting
that should appear weekly in comp.unix.programmer. Administrivia regarding
newsgroup conduct, etc., are also found there; I want to reserve this
document specifically for technical Q's and A's.

All contributions have been edited by the maintainer, therefore any errors
or omissions are my responsibility rather than that of the contributor.

This FAQ is now maintained as Texinfo source; I'm generating a raw text
version for Usenet using the `makeinfo' program, and an HTML version using
`texi2html'.

Copyright (C) 1997, 1998, 1999, 2000 Andrew Gierth. This document may be
distributed freely on Usenet or by email; it may be archived on FTP or WWW
sites that mirror the news.answers archives, provided that all reasonable
efforts are made to ensure that the archive is kept up-to-date. (This
permission may be withdrawn on an individual basis.) It may not be
published in any other form, whether in print, on the WWW, on CD-ROM, or in
any other medium, without the express permission of the maintainer.

List of contributors in no particular order:

Andrew Gierth <andrew@erlenstar.demon.co.uk>
Patrick J. Horgan withheld
Stephen Baynes <stephen.baynes@soton.sc.philips.com>
James Raynard withheld
Michael F. Quigley withheld
Ken Pizzini withheld
Thamer Al-Herbish withheld
Nick Kew <nick.kew@pobox.com>
Dan Abarbanel withheld
Billy Chambless <billy@cast.msstate.edu>
Walter Briscoe <walter@wbriscoe.demon.co.uk>
Jim Buchanan <jbuchana@buchanan1.net>
Dave Plonka <plonka@doit.wisc.edu>
Daniel Stenberg withheld
Ralph Corderoy <ralph@inputplus.demon.co.uk>
Stuart Kemp withheld
Sergei Chernev <ser@nsu.ru>
Bjorn Reese withheld
Joe Halpin <jhalpin@nortel.ca>
Aaron Crane <aaronc@pobox.com>
Geoff Clare <gwc@root.co.uk>

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
affairs continues until the child process either exits, or calls
`execve()', at which point the parent process continues.

This means that the child process of a `vfork()' must be careful to avoid
unexpectedly modifying variables of the parent process. In particular, the
child process must *not* return from the function containing the `vfork()'
call, and it must *not* call `exit()' (if it needs to exit, it should use
`_exit()'; actually, this is also true for the child of a normal `fork()').

1.1.3 Why use _exit rather than exit in the child branch of a fork?
-------------------------------------------------------------------

There are a few differences between `exit()' and `_exit()' that become
significant when `fork()', and especially `vfork()', is used.

The basic difference between `exit()' and `_exit()' is that the former
performs clean-up related to user-mode constructs in the library, and calls
user-supplied cleanup functions, whereas the latter performs only the
kernel cleanup for the process.

In the child branch of a `fork()', it is normally incorrect to use
`exit()', because that can lead to stdio buffers being flushed twice, and
temporary files being unexpectedly removed. In C++ code the situation is
worse, because destructors for static objects may be run incorrectly.
(There are some unusual cases, like daemons, where the *parent* should call
`_exit()' rather than the child; the basic rule, applicable in the
overwhelming majority of cases, is that `exit()' should be called only once
for each entry into `main'.)

In the child branch of a `vfork()', the use of `exit()' is even more
dangerous, since it will affect the state of the *parent* process.

1.2 Environment variables
=========================

1.2.1 How can I get/set an environment variable from a program?
---------------------------------------------------------------

Getting the value of an environment variable is done by using `getenv()'.

#include <stdlib.h>

char *getenv(const char *name);

Setting the value of an environment variable is done by using `putenv()'.

#include <stdlib.h>

int putenv(char *string);

The string passed to putenv must *not* be freed or made invalid, since a
pointer to it is kept by `putenv()'. This means that it must either be a
static buffer or allocated off the heap. The string can be freed if the
environment variable is redefined or deleted via another call to `putenv()'.

Remember that environment variables are inherited; each process has a
separate copy of the environment. As a result, you can't change the value
of an environment variable in another process, such as the shell.

Suppose you wanted to get the value for the `TERM' environment variable.
You would use this code:

char *envvar;

envvar=getenv("TERM");

printf("The value for the environment variable TERM is ");
if(envvar)
{
printf("%s\n",envvar);
}
else
{
printf("not set.\n");
}

Now suppose you wanted to create a new environment variable called `MYVAR',
with a value of `MYVAL'. This is how you'd do it.

static char envbuf[256];

sprintf(envbuf,"MYVAR=%s","MYVAL");

if(putenv(envbuf))
{
printf("Sorry, putenv() couldn't find the memory for %s\n",envbuf);
/* Might exit() or something here if you can't live without it */
}

1.2.2 How can I read the whole environment?
-------------------------------------------

If you don't know the names of the environment variables, then the
`getenv()' function isn't much use. In this case, you have to dig deeper
into how the environment is stored.

A global variable, `environ', holds a pointer to an array of pointers to
environment strings, each string in the form `"NAME=value"'. A `NULL'
pointer is used to mark the end of the array. Here's a trivial program to
print the current environment (like `printenv'):

#include <stdio.h>

extern char **environ;

int main()
{
char **ep = environ;
char *p;
while ((p = *ep++))
printf("%s\n", p);
return 0;
}

In general, the `environ' variable is also passed as the third, optional,
parameter to `main()'; that is, the above could have been written:

#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
char *p;
while ((p = *envp++))
printf("%s\n", p);
return 0;
}

However, while pretty universally supported, this method isn't actually
defined by the POSIX standards. (It's also less useful, in general.)

1.3 How can I sleep for less than a second?
===========================================

The `sleep()' function, which is available on all Unixes, only allows for a
duration specified in seconds. If you want finer granularity, then you need
to look for alternatives:

* Many systems have a function `usleep()'

* You can use `select()' or `poll()', specifying no file descriptors to
test; a common technique is to write a `usleep()' function based on
either of these (see the comp.unix.questions FAQ for some examples)

* If your system has itimers (most do), you can roll your own `usleep()'
using them (see the BSD sources for `usleep()' for how to do this)

* If you have POSIX realtime, there is a `nanosleep()' function

Of the above, `select()' is probably the most portable (and strangely, it
is often much more efficient than `usleep()' or an itimer-based method).
However, the behaviour may be different if signals are caught while asleep;
this may or may not be an issue depending on the application.

Whichever route you choose, it is important to realise that you may be
constrained by the timer resolution of the system (some systems allow very
short time intervals to be specified, others have a resolution of, say,
10ms and will round all timings to that). Also, as for `sleep()', the delay
you specify is only a *minimum* value; after the specified period elapses,
there will be an indeterminate delay before your process next gets
scheduled.

1.4 How can I get a finer-grained version of alarm()?
=====================================================

Modern Unixes tend to implement alarms using the `setitimer()' function,
which has a higher resolution and more options than the simple `alarm()'
function. One should generally assume that `alarm()' and
`setitimer(ITIMER_REAL)' may be the same underlying timer, and accessing it
both ways may cause confusion.

Itimers can be used to implement either one-shot or repeating signals;
also, there are generally 3 separate timers available:

`ITIMER_REAL'
counts real (wall clock) time, and sends the `SIGALRM' signal

`ITIMER_VIRTUAL'
counts process virtual (user CPU) time, and sends the `SIGVTALRM'
signal

`ITIMER_PROF'
counts user and system CPU time, and sends the `SIGPROF' signal; it is
intended for interpreters to use for profiling.

Itimers, however, are not part of many of the standards, despite having
been present since 4.2BSD. The POSIX realtime extensions define some
similar, but different, functions.

1.5 How can a parent and child process communicate?
===================================================

A parent and child can communicate through any of the normal inter-process
communication schemes (pipes, sockets, message queues, shared memory), but
also have some special ways to communicate that take advantage of their
relationship as a parent and child.

One of the most obvious is that the parent can get the exit status of the
child.

Since the child inherits file descriptors from its parent, the parent can
open both ends of a pipe, fork, then the parent close one end and the child
close the other end of the pipe. This is what happens when you call the
`popen()' routine to run another program from within yours, i.e. you can
write to the file descriptor returned from `popen()' and the child process
sees it as its stdin, or you can read from the file descriptor and see what
the program wrote to its stdout. (The mode parameter to `popen()' defines
which; if you want to do both, then you can do the plumbing yourself
without too much difficulty.)

Also, the child process inherits memory segments mmapped anonymously (or by
mmapping the special file `/dev/zero') by the parent; these shared memory
segments are not accessible from unrelated processes.

1.6 How do I get rid of zombie processes?
=========================================

1.6.1 What is a zombie?
-----------------------

When a program forks and the child finishes before the parent, the kernel
still keeps some of its information about the child in case the parent
might need it - for example, the parent may need to check the child's exit
status. To be able to get this information, the parent calls `wait()';
when this happens, the kernel can discard the information.

In the interval between the child terminating and the parent calling
`wait()', the child is said to be a `zombie'. (If you do `ps', the child
will have a `Z' in its status field to indicate this.) Even though it's
not running, it's still taking up an entry in the process table. (It
consumes no other resources, but some utilities may show bogus figures for
e.g. CPU usage; this is because some parts of the process table entry have
been overlaid by accounting info to save space.)

This is not good, as the process table has a fixed number of entries and it
is possible for the system to run out of them. Even if the system doesn't
run out, there is a limit on the number of processes each user can run,
which is usually smaller than the system's limit. This is one of the
reasons why you should always check if `fork()' failed, by the way!

If the parent terminates without calling wait(), the child is `adopted' by
`init', which handles the work necessary to cleanup after the child. (This
is a special system program with process ID 1 - it's actually the first
program to run after the system boots up).

1.6.2 How do I prevent them from occuring?
------------------------------------------

You need to ensure that your parent process calls `wait()' (or `waitpid()',
`wait3()', etc.) for every child process that terminates; or, on some
systems, you can instruct the system that you are uninterested in child
exit states.

Another approach is to `fork()' *twice*, and have the immediate child
process exit straight away. This causes the grandchild process to be
orphaned, so the init process is responsible for cleaning it up. For code
to do this, see the function `fork2()' in the examples section.

To ignore child exit states, you need to do the following (check your
system's manpages to see if this works):

struct sigaction sa;
sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
sa.sa_flags = SA_NOCLDWAIT;
#else
sa.sa_flags = 0;

No comments:

Post a Comment