Linux/C Development
[Reference] SAMS-Linux_Programming_Unleashed_Second_Edition
[Reference] POSIX Thread, RealTime and IPC
[ Libraries ]
Library (.so and .a) Directory:
gcc default : -L > LIBRARY_PATH > /lib, /usr/lib, /usr/local/lib
Header File Directory
gcc default: -I > C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH > /usr/include/, /usr/local/include/, /usr/lib/gcc/i686-redhat-linux/…/include/
Linux Dynamic Linking
/lib/ld-linux.so.2 (ld-2.12.so) :
- dynamic linker/loader
- search .so files in LD_PRELOAD, /etc/ld.so.preload, LD_LIBRARY_PATH, and /etc/ld.so.cache./etc/ld.so.cache :
- shared library list, used by ld.so (or ld-linux.so) when loading executables.
-ldconfig -p
: display the /etc/ld.so.cache in man-readable format.
ldconfig [-v] [dir]
:
- update the /etc/ld.so.cache by .so files found in /lib, /usr/lib, ‘dir’ and ‘/etc/ld.so.conf’.
ldd <file>
: list the shared libraries a program requires in order to run.
Make Archive (.a):
gcc [-H] -c <source-files>
: make .o files
ar -rcs <archive-name> <files...>
: create archive (.a file).
Make Shared Object (.so):
gcc -fPIC [-g] -c <source-files>
: make .o files
- e.g.gcc -fPIC -g -c liberr.c -o liberr.o
gcc [-g] -shared -Wl,-soname,<so-file-name> -o <so-file-name> <obj-files> -lc
: make .so file
- e.g.gcc -g -shared -Wl,-soname,liberr.so -o liberr.so.1.0.0 liberr.o -lc
Use Archive (.a) / Shared Object (.so):
gcc [-g] <src-file> -o <executable> [-L<dir>] -l<short-so-name / short-archive-name>
- e.g.gcc -g errtest.c -o errtest -L. -lerr
: to link with liberr.so or liberr.a in current dir.
List Symbols
nm [-Csl]
: list symbols in a object file.
Symbol Type:
U : Undefined symbols.
b, B : symbols in BSS section.
d, D : symbols in DATA section.
r, R : symbols in ReadOnly DATA section.
t, T : symbols in TEXT section.
V, W : weak symbols.
[ Debug ]
- gdb
- printing and logs
- time
//print a string (if s is not null), followed by a message describing the last error encountered during a call to a system or library function.
void perror(const char *s);
[ I/O - System Calls ]
System Call Based I/O
- File descriptor is an integer (index to open file table).
- 0 for stdin, 1 for stdout, 2 for stderr
Mainly for device control, socket and pipe, sound card.
System Calls
int open(const char *pathname, int flags, mode_t mode);
// flags: O_RDWR, O_NONBLOCK, O_SYNC, etc.
// return: -1 for error. int errno, char * strerror(int);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
//Change flags and mode. Can be used for enabling the non-blocking mode.
int fcntl(int fd, int cmd, ...);
//cmd: F_GETFL for getting options, F_SETFL for setting options.
Sample Code:
{ // set socket to non-blocking:
save_file_flags = fcntl(in_socket_descriptor, F_GETFL);
save_file_flags |= O_NONBLOCK;
fcntl(in_socket_descriptor, F_SETFL, save_file_flags);
}
//for device control, mainly handled by device driver.
//E.g. set baut-rate of a serial port.
int ioctl(int d, int request, ...);
//create a epoll (can hold size file descriptor)
int epoll_create(int size);
// return: epfd, or -1 for error
//add/remove fd and watched event into epoll
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// op: EPOLL_CTL_ADD/EPOLL_CTL_DEL/EPOLL_CTL_MOD
// return: 0 for ok, -1 for error
struct epoll_event {
__uint32_t events; // epoll events
epoll_data_t data; // user data variable
};
//events: EPOLLIN, EPOLLOUT, EPOLLERR, EPOLLHUP, EPOLLET
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
//wait for an I/O event on an epoll file descriptor
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
//events: the detected event
//return: >0 (the number of file descriptors ready for the requested I/O), 0 (no event detected), -1 (error)
off_t lseek(int fildes, off_t offset, int whence);
int dup(int oldfd);
int dup2(int oldfd, int newfd);
//duplicate file descriptor.
int fsync(int fd);
//flush data to disk or device.
int ftruncate(int fd, size_t length);
//truncate the file.
int fstat(int filedes, struct stat *buf);
//get the information about a file.
int fchown(int fd, uid_t owner, gid_t group);
//change the owner and group of a file.
int fchmod(int fildes, mode_t mode);
//chmod
int pipe(int pipefd[2]);
//create a pipe, pipefd[0] for read and pipefd[1] for write.
int flock(int fd, int operation)
//apply or remove an advisory lock on an open file
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
[ I/O - stdio ]
stdio, buffered i/o.
Mainly for file manipulation (not for device control).
Built on top of I/O System Calls.
library functions:
FILE *fopen(const char *path, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fclose(FILE * stream);
void clearerr( FILE *stream);
int feof( FILE *stream);
int ferror( FILE *stream);
int fileno( FILE *stream);
int fprintf(FILE *stream, const char *format, ...
int fscanf( FILE *stream, const char *format, ...);
int printf(const char *format, ...);
int puts(const char *s);
//writes the string s and a trailing newline to stdout.
char *gets(char *s);
//reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with '\0'.
int getchar(void);
//equivalent to getc(stdin), get a char from stdin.
[ POSIX Thread (pthread) ]
Reference: tutorial - pthread
Notice:
- Compile and link with -pthread !
- ulimit -a
to check resource limitation
- threads are terminated if parent process is terminated.
APIs - Mostly Often Used
//thread creation
int pthread_create (pthread_t *thread_id, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
//terminate the calling thread
void pthread_exit(void *retval);
//blocked if any child thread is still alive.
APIs - Inter-Thread Control
//send a cancellation request to a thread
int pthread_cancel(pthread_t thread);
//blocks the calling thread until the specified thread terminates.
int pthread_join(pthread_t thread, void **retval);
/*-------------------------------------------*/
//to get the real pid of a thread
syscall(SYS_gettid);
//get thread id
pthread_t pthread_self(void)
//check if t1 and t2 is the same.
int pthread_equal(pthread_t t1, pthread_t t2);
/*---------- pthread mutex ------------------*/
//mutex init method-1
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//mutex init method-2
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//attr can be NULL
//mutex taken/release
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//return error if (a)mutex is already unlocked (b)mutex is not owned by the calling thread.
//mutex termination
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/*---------- pthread condition ------------------*/
//condition init-1
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//condition init-2
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//attr can be NULL
//block the calling thread until a a condition is signaled.
//used together with mutex!
//check sample code (on the internet) for reference!
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
//signal (wakeup) a thread waiting on a condition.
int pthread_cond_signal(pthread_cond_t *cond);
//used if more than 1 thread is in blocking state.
int pthread_cond_broadcast(pthread_cond_t *cond);
//condition termination
int pthread_cond_destroy(pthread_cond_t *cond);
Sample Code:
//receiver side
{
pthread_mutex_lock(& lock);
while(is_queue_empty())
pthread_cond_wait(& cond, & lock);
/* Something in the queue, and we have the mutex ! */
pthread_mutex_unlock(& lock);
}
//sender side
{
pthread_mutex_lock(& lock);
/* Add something to the queue */
pthread_mutex_unlock(& lock);
pthread_cond_signal(& cond);
}
APIs - Thread Attributes
//init a thread attribute object
int pthread_attr_init(pthread_attr_t *attr);
//attribute: joinable or detached
pthread_attr_setdetachstate()
//destroy the attribute object after the thread is created.
int pthread_attr_destroy(pthread_attr_t *attr);
//Example Code:
{
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr); //init the attribute object.
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //make it joinable.
pthread_create(&thread, &attr, thread_proc, NULL);
pthread_attr_destroy(&attr); //destroy the attribute after use.
}
APIS - Fine Tune
//stack related
pthread_attr_getstacksize (attr, stacksize)
pthread_attr_setstacksize (attr, stacksize)
pthread_attr_getstackaddr (attr, stackaddr)
pthread_attr_setstackaddr (attr, stackaddr)
//set/get affinity of a thread/process, NOT portable!
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);
int sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
void CPU_CLR(int cpu, cpu_set_t *set);
int CPU_ISSET(int cpu, cpu_set_t *set);
void CPU_SET(int cpu, cpu_set_t *set);
void CPU_ZERO(cpu_set_t *set);
//pthread mutex attribute object
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
[ Linux Process Handling ]
//create a child process
pid_t fork(void);
//clone() is mainly used for pthread_create(), very seldome used directly.
//get my pid
pid_t getpid(void);
//get the pid of parent process
pid_t getppid(void);
//send a signal to a process
int kill(pid_t pid, int sig);
//register a signal handler
sighandler_t signal(int signum, sighandler_t handler);
[ IPC - Pipe]
It is kind of replacing by socket.
one-way communication channel.
unamed pipe : mainly for parent-child process communication.
#define INPUT 0
#define OUTPUT 1
int file_descriptors[2]; //0 for input, 1 for output
pipe(file_descriptors); //create the unamed pipe
...
//write to pipe
write(file_descriptors[OUTPUT], data_p, sizeof(data_p));
//read from pipe
returned_count = read(file_descriptors[INPUT], buf, sizeof(buf));
...
close(file_descriptors[0]); //close the input end
close(file_descriptors[0]); //close the output end
named pipe (FIFO) : mainly for communications between different programs that share a common file system.
mknod <pipe-file-name> mypipe #to create a named pipe (mypipe) in the fs (current directory)
open(), read(), write(), close() //to read or write from named pipe.
fopen(), fread(), fwrite(), fclose() //to read or write from named pipe.
[ Socket ]
APIs - Mostly Often Used
// socket creation
int socket (int domain, int type, int protocol)
- domain: AF_UNIX, AF_INET
- type: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW (for AF_INET). can | with SOCK_NONBLOCK and SOCK_CLOEXEC.
- protocol: 0 in most case
- return: socket handler or -1 (error)// create a pair of connected sockets
int socketpair(int domain, int type, int protocol, int sv[2]);
- refer to socket() for input parameter explanation.
- return: 0 for ok, -1 for error.// associate a process with a socket (with certain address)
int bind (int sockfd, struct sockaddr * my_addr, int my_addr_length)
- my_addr: local address
- return: 0 for ok, -1 for error
struct sockaddr //16 bytes totally
{
sa_family_t sa_family; //short, AF_INET, AF_UNIX, etc.
char sa_data[14]; //14 bytes
}
struct sockaddr_un //16 bytes for AF_UNIX
{
sa_family_t sun_family; //AF_UNIX or PF_UNIX
char sun_path[UNIX_PATH_MAX]; //socket path, 3 types (unnamed, path in fs, abstract)
}
struct sockaddr_in //16 bytes, for AF_INET
{
short sin_family; //=AF_INET
unsigned short sin_port; //htons()
struct in_addr sin_addr; //e.g inet_addr("192.168.0.1") or sin.sin_addr.s_addr = INADDR_ANY;
unsigned char sin_zero[8]; //padding
}
//convert values between host and network byte order
uint16_t htons(uint16_t hostshort);
uint16_t ntohs(uint16_t netshort);
uint32_t htonl(uint32_t hostlong);
uint32_t ntohl(uint32_t netlong);
//internet address manipulation
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);
//hostname <-> ip address
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
//change socket options
flags = fcntl(sockfd,F_GETFL,0); //get a sock option
fcntl(sockfd,F_SETFL,flags|O_NONBLOCK); //set as non-blocking.
// mark the socket as passive socket (can accept incoming connection requests).
int listen (int sockfd, int input_queue_size)
- sockfd: socket handler.
- input_queue_size: incoming connection request queue size.
- return: 0 for ok, -1 for error// accept a connection on a socket. can block the caller.
int accept (int sockfd, struct sockaddr *addr, socklen_t *addrlen)
- addr: address of the remote peer
- return: a new socket. -1 for error// to connect to a remote socket. can block the caller.
int connect (int sockfd, struct sockaddr * server_address, int server_address_length)
- sockfd: socket handler.
- server_address: remote server address
- return: 0 for ok, -1 for error// send a message on a socket
ssize_t send (int sockfd, const void *buf, size_t len, int flags);
- the same as wirte() if no flags.
- flags: MSG_DONTWAIT (non-blocking), etc.
size_t sendto (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
return: the number of characters sent, or -1 for error.//receive a message from a socket
ssize_t recv (int sockfd, void *buf, size_t len, int flags);
- the same as read() if no flags.
- flags: MSG_DONTWAIT (non-blocking), etc.
ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
return: the number of characters received, or -1 for error.
APIs - Not Very Often Used
// get address that the sockfd is bound.
int getsockname (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
return: 0 for ok, -1 for error// get address of the remote peer.
int getpeername (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
return: 0 for ok, -1 for error// set/get socket options
int getsockopt (int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen);
// level: often IPPROTO_IP;
[ IPC - System V]
Obsoleted
[ IPC - POSIX]
Message Queue
Semaphore
Shared Memory
Linux Tools : ipcs
, ipcrm
, ipcmk
[ Crucial Dirs & Files ]
/dev/mem : full physical memory map. normally used with mmap().