Unix Programming
Table of Contents
References
1 Low-level IO
1.1 open
int open(const char *filename, int flags[, mode_t mode])
Create and return a file descriptor.
1.2 close
int close(int filedes)
- file descriptor is deallocated
- if all file descriptors associated with a pipe are closed, any unread data is discarded.
Return
- 0 on success, -1 on failure
1.3 read
ssize_t read(int filedes, void *buffer, size_t size)
- read up to size bytes, store result in buffer.
Return
- number of bytes actually read.
- return 0 means EOF
1.4 write
ssize_t write(int filedes, const void *buffer, size_t size)
- write up to size bytes from buffer to the file descriptor.
Return
- number of bytes actually written
- -1 on failure
1.5 fdopen
FILE *fdopen(int filedes, const char *opentype)
from file descriptor, get the stream
1.6 fileno
int fileno(FILE *stream)
from stream to file descriptor
1.7 fdset
This is a bit array.
- FDZERO(&fdset): initialise fdset to empty
- FDCLR(fd, &fdset): remove fd from the set
- FDSET(fd, &fdset): add fd to the set
- FDISSET(fd, &fdset): return non-0 if fd is in set
1.8 select - synchronous I/O multiplexing
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
Block until at least one fd is true for specific condition, unless timeout.
Params
- nfds: the range of file descriptors to be tested. Should be the
largest one in the sets + 1. But just pass
FD_SETSIZE
. - readfds: watch for read. can be NULL.
- writefds: watch for write. can be NULL.
- errorfds: watch for error. can be NULL.
- timeout:
- NULL: no timeout, block forever
- 0: return immediately. Used for test file descriptors
Return:
- if timeout, return 0
- the sets are modified. Those in sets are those ready
- return the number of ready file descriptors in all sets
int fd; // init fd fd_set set; FD_ZERO(&set) FD_SET(fd, &set); struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; select(FD_SETSIZE, &set, NULL, NULL, &timeout);
1.9 sync
void sync(void) // sync all dirty files int fsync(int filedes) // sync only that file
1.10 dup
You can create a new descriptor to refer to the same file. They
- share file position
- share status flag
- seperate descriptor flags
int dup(int old) // same as fcntl(old, F_DUPFD, 0)
Copy old to the first available descriptor number.
int dup2(int old, int new) // same as close(new) fcntl(old, F_DUPFD, new)
If old is invalid, it does nothing (does not close new
)!
2 Date and Time
- calendar time: absolute time, e.g. 2017/6/29
- interval: between two calendar times
- elapsed time: length of interval
- amount of time: sum of elapsed times
- period: elapsed time between two events
- CPU time: like calendar time, but relative to process, i.e. when the process run on CPU
- Processor time: amount of time a CPU is in use.
2.1 struct timeval
- timet tvsec: seconds
- long int tvusec: micro seconds, must be less than 1 million
2.2 struct timespec
- timet tvsec
- long int tvnsec: nanoseconds. Must be less than 1 billion
2.3 difftime
double difftime (time_t time1, time_t time0)
2.4 timet
On GNU it is long int. It should be the seconds elapsed since 00:00:00 Jan 1 1970, Coordinated Universal Time.
get current calenddar time:
time_t time(time_t *result)
2.5 alarm
2.5.1 struct itimerval
- struct timeval itinterval: 0 to send alarm once, non-zero to send every interval
- struct timeval itvalue: time left to alarm. If 0, the alarm is disabled
2.5.2 setitimer
int setitimer(int which, const struct itimerval *new, struct itimerval *old)
- which: ITIMERREAL, ITIMERVIRTUAL, ITIMERPROF
- new: set to new
- old: if not NULL, fill with old value
2.5.3 getitimer(int which, struct itimerval *old)
get the timer
2.5.4 alarm
unsigned int alarm(unsigned int seconds)
To cancel existing alarm, use alarm(0). Return:
- 0: no previous alarm
- non-0: the remaining value of previous alarm
unsigned int alarm (unsigned int seconds) { struct itimerval old, new; new.it_interval.tv_usec = 0; new.it_interval.tv_sec = 0; new.it_value.tv_usec = 0; new.it_value.tv_sec = (long int) seconds; if (setitimer (ITIMER_REAL, &new, &old) < 0) return 0; else return old.it_value.tv_sec; }
3 Process
Three steps
- create child process
- run an executable
- coordinate the results with parent
3.1 system
int system(const char *command)
- use
sh
to execute, and search in $PATH - return -1 on error
- return the status code for the child
3.2 getpid
- pidt getpid(void): return PID of current process
- pidt getppid(void): PID of parent process
3.3 fork
pid_t fork(void)
return
- 0 in child
- child's PID in parent
- -1 on error
3.4 exec
int execv (const char *filename, char *const argv[]) int execl (const char *filename, const char *arg0, ...) int execve (const char *filename, char *const argv[], char *const env[]) int execle (const char *filename, const char *arg0, ..., char *const env[]) int execvp (const char *filename, char *const argv[]) int execlp (const char *filename, const char *arg0, ...)
- execv: the last of argv array must be NULL. All strings are null-terminated.
- execl: argv are seperated, the last one must be NULL
- execve: provide env
- execle
- execvp: find filename in $PATH
- execlp
3.5 wait
This should be used in parent process.
pid_t waitpid(pid_t pid, int *status_ptr, int options)
- pid:
- positive: the pid for a child process
- -1 (WAITANY): any child process
- 0 (WAITMYPGRP): any child process that has the same process group ID as the parent
- -pgid (any other negative value): any child process having the process group ID as gpid
- options: OR of the following
- WNOHANG: no hang: the parent process should not wait
- WUNTRACED: report stopped process as well as the terminated ones
- return: PID of the child process that is reporting
pid_t wait(int *status_ptr)
wait(&status)
is same as waitpid(-1, &status, 0)
3.5.1 Status
The signature is int NAME(int status)
.
- WIFEXITED: if exited: return non-0 if child terminated normally with exit
- WEXITSTATUS: exit status: if above true, this is the low-order 8 bits of the exit code
- WIFSIGNALED: if signaled: non-0 if the process terminated because it receives a signal that was not handled
- WTERMSIG: term sig: if above true, return that signal number
- WCOREDUMP: core dump: non-0 if the child process terminated and produce a core dump
- WIFSTOPPED: if stopped: if the child process stopped
- WSTOPSIG: stop sig: if above true, return the signal number that cause the child to stop
3.5.1.1 TODO What is the difference between terminate and stop?
4 Tmp
4.1 poll - input/output multiplexing
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
4.2 sigaction
// handler must be void (*) (int) void handle_signal(int signal) { // should be alarm if (signal != SIGALRM) { std::cerr << "Wrong signal: " << signal << "\n"; } } int main() { struct sigaction sa; sa.sa_handler = &handle_signal; sigaction(SIGALRM, &sa, NULL); ualarm(timeout_usec, 0); }
4.3 execvp
4.4 pipe
int pipe(int filedes[2])
- Create a pipie and puts the filedes[0] for reading, filedes[1] for writing
Return:
- 0 on success, -1 on failure
4.5 timeradd
void timeradd(struct timeval *a, struct timeval *b, struct timeval *res); void timersub(struct timeval *a, struct timeval *b, struct timeval *res); void timerclear(struct timeval *tvp); int timerisset(struct timeval *tvp); int timercmp(struct timeval *a, struct timeval *b, CMP);
- timeradd: res = a+b
- timersub: res = a-b
4.6 kill
int kill(pid_t pid, int sig)