Linux/C Development Handbook

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().

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值