常用 Unix 函数总结

1. 文件操作

文件流操作

#include <stdio.h>

打开,关闭
FILE* fopen(const char* filename, const char* mode);
int fclose(FILE* stream);


数据块读写,大小为 size * numb
size_t fread(void *ptr, size_t size, size_t numb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t numb, FILE *stream);

格式化读,由format参数指定读的数据格式,由 ... 参数指定接收的容器
int fscanf(FILE *stream, const char *format, );
int fprintf(FILE *stream, const char *format, ...);


int scanf(const char *format, );
int printf(const char *format, ...);
//相当于fprintf(stdout,format,…);

从字符串中读取指定的格式
int sscanf(char *str, const char *format, );
int sprintf(char *str, const char *format, ...);
//eg:sprintf(buf,”the string is;%s”,str);



字符读写
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
int getc(FILE *stream);//等同于 fgetc(FILE* stream)
int putc(int c, FILE *stream);//等同于 fputc(int c, FILE* stream)
int getchar(void);//等同于 fgetc(stdin);
int putchar(int c);//等同于 fputc(int c, stdout);

单行读写
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);//等同于 fputs(const char *s,stdout);
char *gets(char *s);//等同于 fgets(const char *s, int size, stdin);

文件定位
int feof(FILE * stream);
//通常的用法为while(!feof(fp))
int fseek(FILE *stream, long offset, int whence);
//设置当前读写点到偏移whence 长度为offset处
long ftell(FILE *stream);
//用来获得文件流当前的读写位置
void rewind(FILE *stream);
//把文件流的读写位置移至文件开头 fseek(fp, 0, SEEK_SET);

文件权限
#include <sys/stat.h>
int chmod(const char* path, mode_t mode);

目录操作

获取,改变当前目录
#include <unistd.h> //头文件
char *getcwd(char *buf, size_t size); //获取当前目录,相当于pwd命令
getcwd(NULL, 0);
int chdir(const char *path); //修改当前目录,即切换目录,相当于cd命令


创建,删除
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int mkdir(const char *pathname, mode_t mode); //创建目录,mode是目录权限
int rmdir(const char *pathname); //删除目录

其他操作
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //打开一个目录
struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针
void rewinddir(DIR *dir); //重新定位到目录文件的头部
void seekdir(DIR *dir,off_t offset);//用来设置目录流目前的读取位置
off_t telldir(DIR *dir); //返回目录流当前的读取位置
int closedir(DIR *dir); //关闭目录文件

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf); //获取文件状态

目录项 和 iNode节点

目录项(只保存文件的最基本信息)
struct dirent{
ino_t d_ino; //该文件的inode
off_t d_off; //到下一个dirent的偏移
unsigned short d_reclen;//文件名长度
unsigned char d_type; //所指的文件类型
char d_name[256]; //文件名
};


iNode节点(保存文件的所有信息)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //打开一个目录
struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针
void rewinddir(DIR *dir); //重新定位到目录文件的头部
void seekdir(DIR *dir,off_t offset);//用来设置目录流目前的读取位置
off_t telldir(DIR *dir); //返回目录流当前的读取位置
int closedir(DIR *dir); //关闭目录文件
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

文件描述符操作

打开,创建,读写,关闭

#include <sys/types.h> //头文件
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags); //文件名 打开方式
int open(const char *pathname, int flags, mode_t mode);//文件名 打开方式 权限
int creat(const char *pathname, mode_t mode); //文件名 权限
//creat现在已经不常用了,它等价于
open(pathname,O_CREAT|O_TRUNC|O_WRONLY,mode);
int close(int fd);//fd表示文件描述词,是先前由open或creat创建文件时的返回值。

读写
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);//文件描述符 缓冲区 长度
ssize_t write(int fd, const void *buf, size_t count);

改变文件大小
#include <unistd.h>
int ftruncate(int fd, off_t length);

文件映射
void *mmap(void *adr, size_t len, int prot, int flag, int fd, off_t off);
char *p;
p = (char *)mmap(NULL,5,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

文件定位(内核缓冲区)
off_t lseek(int fd, off_t offset, int whence);//fd文件描述词


获取文件信息
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf); //文件名 stat结构体指针
int fstat(int fd, struct stat *buf); //文件描述词 stat结构体指针


文件描述符的复制
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);

2. 进程操作

进程属性

pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);

pid_t fork(void);

int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg0, ... /*, (char *)0, char *const
envp[] */);
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
int execvp(const char *file, char *const argv[]);


pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);



void exit(int status);//可以看出exit函数是由ISO C规定的
void _exit(int status;//_exit是一个Linux系统调用
void _Exit(int status);//_Exit是ISO C规定的库函数
           
pid_t getpgrp(void);//获取进程组ID
pid_t getpgid(pid_t pid);//获取PID为pid的进程的进程组ID,如果pid为0,则获取本进程所属进程组ID
int setpgid(pid_t pid, pid_t pgid);//将pid进程的进程组ID设置为pgid
//如果pid为0,使用调用者的进程ID
//如果pgid为0,则进程组ID和pid一致

pid_t setsid(void); //以当前进程为组长创建一个新会话  
pid_t getsid(pid_t pid); //获取指定进程的会话id

                    
           

进程间通信

匿名管道
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
           
#include <unistd.h>
int pipe(int pipefd[2]);

有名管道
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int mkfifo(const char *pathname, mode_t mode);
int rename(const char *oldpath, const char *newpath); //重命名
int unlink(const char *path); //删除硬链接
int link(const char *oldpath, const char *newpath); //创建硬链接
//注意这里的newpath必须是文件名而不是目录名


XSI IPC    
>> ipcs
>> ipcrm -m shmid  
           
共享内存
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
key_t ftok(const char *pathname, int proj_id); //用file 生成key
int shmget(key_t key, size_t size, int shmflg); //创建或者获取一个共享内存区段或者私有共享内存区,如果参数key的取值是宏 IPC_PRIVATE 共享内存段是私有的
void *shmat(int shmid, const void *shmaddr, int shmflg); //连接到一个共享内存区段
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf); //修改共享区段属性
使用 shmctl 可以用于对共享内存段执行多种操作。根据cmd参数的不同,可以执行不同的操作:
           IPC_STAT可以用来获取存储共享内存段信息的数据结构
           IPC_SET可以用来修改共享内存段的所有者、所在组和权限; 
           IPC_RMID可以用来从内核删除共享内存段,当删除时,无论此时有多少进程映射到共享内存段,它都会被标记为待删除,一旦被标记以后,就无法再建立映射了。当最后一个映射解除时,共享内存段就真正被移除。
           

信号量
int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);
在函数 semctl 中,
           semid参数是信号量的标识符,就是 semget 的返回值,
           semnum表示某个信号量值在信号量集合中的索引(范围从0开始)
           cmd参数表示要执行的操作
           IPC_STAT表示要获取信号量状态,可变参数要设置为状态结构体的指针;
           IPC_SET表示要设置信号量状态,可变参数要设置为状态结构体的指针;
           IPC_RMID表示要删除信号量,不需要设置可变参数,注意和共享内存的删除不同,信号量是立即删除的;
           GETVAL表示获取置某个信号量值,可变参数传入数值
           SETVAL表示设置某个信号量值,可变参数传入数值;
           GETALL和SETALL表示获取和设置信号量集合,可变参数传入一个短整型数组或者不写。
struct sembuf{
    unsigned short sem_num; /* semaphore number */
    short sem_op; /* semaphore operation */
    short sem_flg; /* operation flags */
}
int semop(int semid, struct sembuf *sops, size_t nsops);

//这个由用户自己声明,用于取出信号量的属性时使用
union semun{
    int val; //val for SETVAL
    struct semid_ds *buf; //buffer for IPC_STAT,IPC_SET
    unsigned short *arry; //Array for GETALL,SETALL
}           

           
           
消息队列
int msgget(key_t key, int msgflg);
           
struct mymesg{
    long mtype;
    char mtext[1];
};
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
msgctl(msgid,IPC_RMID,NULL);//删除是即时的

           
           
信号
typedef void (*sighandler_t)(int);
注册信号方式1
sighandler_t signal(int signum, sighandler_t handler);

struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    /*
        typedef struct
        {unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];} 
        __sigset_t;
        typedef __sigset_t sigset_t; //sigset_t的本质就是一个位图,共有1024位
        int sigemptyset(sigset_t *set); //初始化信号集,清0所有信号
        int sigfillset(sigset_t *set);  //初始化信号集,置1所有信号
        int sigaddset(sigset_t *set, int signum); //增加信号
        int sigdelset(sigset_t *set, int signum); //删除信号
        int sigismember(const sigset_t *set, int signum); //检查信号处于信号集之中
    */
    int sa_flags;
    /*
    	SA_SIGINFO   表示选择sa_sigaction而不是sa_handler作为回调函数
        SA_RESETHAND 处理完捕获的信号以后,信号处理回归到默认,使用情况较少
        SA_NODEFER   解除所有阻塞行为。特别地,执行信号处理流程可以处理同类信号传递,按照栈的方式执行。
        SA_RESTART   让低速系统调用可以自动重启
	*/
    void (*sa_restorer)(void);
};
注册信号方式2
int sigaction(int signum, const struct sigaction *act, struct sigaction
*oldact);

sigset_t pendingSet;
int sigpending(&pendingSet); //获取当前所有未决信号(已经产生没有递送的信号)的集合

使用系统调用 sigprocmask 可以实现全程阻塞的效果
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 
           	how 
            SIG_BLOCK 新的屏蔽字是set和当前屏蔽字的并集
            SIG_UNBLOCK 新的屏蔽字是set的补集和当前屏蔽字的交集
            SIG_SETMASK 新的屏蔽字是set
/*
	sigemptyset(&mask);
    sigaddset(&mask,SIGINT);
    int ret = sigprocmask(SIG_BLOCK,&mask,NULL);
    ret = sigprocmask(SIG_UNBLOCK,&mask,NULL);
*/
sigprocmask 可以和  sigpending 之间配合使用
                
                
           
系统调用 
int kill(pid_t pid, int sig);  
int pause(void);  //来阻塞一个进程,直到某个信号被递送时,进程会解除阻塞
/*
	#if 1
        sigprocmask(SIG_UNBLOCK,&mask,NULL);
        pause();//无法就绪
    #else
        sigset_t waitset;
        sigemptyset(&waitset);
        sigsuspend(&waitset);//使用sigsuspend会捕获临界区当中的信号
    #endif

*/

3. 时钟

#include <sys/time.h>

间隔定时器,类似于相机自动拍摄,当设置拍摄第一张照片的时间后,每间隔一段相同的时间连续自动拍摄(溢出)
struct itimerval 
{
    struct timeval it_interval; /* Interval for periodic timer */
    struct timeval it_value; /* Time until next expiration */  
};

int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
ITIMER_REAL    会记录真实的时间(也就是时钟时间),当时间到时,会产生一个SIGALRM信号
ITIMER_VIRTUAL 会记录用户态模式下的CPU时间,当时间到的时候,会产生一个SIGVTALRM信号
ITIMER_PROF    会记录用户态以及内核态的CPU时间,当时间到的时候,会产生一个SIGPROF信号
安装信号捕捉handler函数捕捉信号,并且打印时间即可

相关结构体
struct timeval 
{
    time_t tv_sec; /* seconds */
    suseconds_t tv_usec; /* microseconds */
};
struct timezone 
{
    int tz_minuteswest;     /* minutes west of Greenwich */
    int tz_dsttime;         /* type of DST correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
#include <time.h>

time_t time(time_t *tloc);

struct tm 
{
    int tm_sec;    /* Seconds (0-60) */
    int tm_min;    /* Minutes (0-59) */
    int tm_hour;   /* Hours (0-23) */
    int tm_mday;   /* Day of the month (1-31) */
    int tm_mon;    /* Month (0-11) */
    int tm_year;   /* Year - 1900 */
    int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    int tm_isdst;  /* Daylight saving time */
};
struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
time_t mktime(struct tm *tm);

ctime(), gmtime() localtime() functions all take an argument of data type  time_t,
    On success, gmtime() and localtime() return a pointer to a struct tm.
    On success, asctime() and ctime() return a pointer to a string.
    

4. 线程操作

错误处理

char *strerror(int errnum);
#define STRERROR_CHECK(ret,msg) {if(ret!=0){fprintf(stderr, "%s:%s\n", msg,strerror(ret));}}


#define PERROR_CHECK(ret , error_val, fileName) { if(ret == error_val){ perror(fileName); return -1; }}

线程操作

查看线程状态
>> ps -elLf
>> top -H    



创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
									void *(*start_routine) (void *), void *arg);

获取线程ID
pthread_t pthread_self(void);

线程退出
void pthread_exit(void *retval);

线程资源回收
int pthread_join(pthread_t thread, void **retval);

线程取消
int pthread_cancel(pthread_t thread);
void pthread_testcancel(void)   //设置cancelation point

线程资源清理
void pthread_cleanup_push(void (*routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);

互斥锁

pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t
*mutexattr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);

条件变量

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const
struct timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);

5. 网络编程

地址信息转换

//man 7 ip

套接字二元组
/* Internet address. */
struct sockaddr_in 
{
    sa_family_t sin_family; /* address family: AF_INET */
    in_port_t sin_port; /* port in network byte order */
    
/* struct in_addr { uint32_t s_addr; };*/
    struct in_addr sin_addr; /* internet address */
}    

 /* address in network byte order */
};




#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

字节序转换
//  h:host	    n:net	   l:32bit    	s:16bit
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

IP地址转换成文本
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size); // inet_ntop - convert IPv4 and IPv6 addresses from binary to text form

网络字节序<----->点分十进制相互转换
int inet_aton(const char *cp, struct in_addr *inp);
== in_addr_t inet_addr(const char *cp);

char *inet_ntoa(struct in_addr in);
//线程安全版本是inet_atop inet_ptoa


获取某域名的IP相关信息
#include <netdb.h>
struct hostent *gethostbyname(const char *name); //传入参数
struct hostent 
{
    char *h_name; /* official name of host */
    char **h_aliases; /* alias list */
    int h_addrtype; /* host address type */
    int h_length; /* length of address */
    char **h_addr_list; /* list of addresses */
}

套接字编程

#include <sys/socket.h>

创建套接字
//domain AF_INET --> IPv4 AF_INET6 --> IPv6
//type SOCK_STREAM --> TCP SOCK_DGRAM --> UDP
//protocol IPPROTO_TCP --> TCP IPPROTO_UDP -->UDP
int socket(int domain, int type, int protocol);

TCP
    
客户端
	1.  int socket(int domain, int type, int protocol);
	2.  int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	3.  ssize_t send(int sockfd, const void *buf, size_t len, int flags);
		ssize_t recv(int sockfd, void *buf, size_t len, int flags);




服务器
	1.  int socket(int domain, int type, int protocol);
	2.  int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
    3.  int listen(int sockfd, int backlog);
    4.  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
	5.  ssize_t send(int sockfd, const void *buf, size_t len, int flags);
        ssize_t recv(int sockfd, void *buf, size_t len, int flags);
		

UDP

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

epoll

1. 创建epoll文件对象
int epoll_create(int size);

2. 设置事件合集
struct epoll_event {
    uint32_t events; /* Epoll events */
    
    epoll_data_t data; /* User data variable */
    /*typedef union epoll_data {
            void *ptr;
            int fd;
            uint32_t u32;
            uint64_t u64;
	} epoll_data_t;*/
};
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);

3. 等待事件
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);