Linux 常用函数
文件操作
C语言库函数
-
FILE *fopen(const char *pathname, const char *mode);
- pathname:文件位置
- mode:模式
- r:只读
- r+:读写,不会创建
- w:只写,会覆盖原文件
- w+:读写,不会覆盖原文件,会创建
- a:添加
- a+:可读可写可创建,初始读位置在文件开始,输出位置在文件末尾
- 备注:除了a,a+,其他模式都是从文件起始位置开始
- return 成功返回一个结构体指针,失败返回NULL
-
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);
- ptr:读入(写入)数据的起始指针,void*可以接受任何类型的指针
- size:每次读入(写入)数据的字节数
- nmemb:读入(写入)数据的次数
- stream:文件流指针
- return:返回读入(写入)的字节数,失败返回-1
- 解释:从文件指针stream中读入nmemb次数据,每次size个字节,存入ptr中
- fwrite和fread类似
-
int fseek(FILE *stream, long offset, int whence);
- stream:文件指针
- offset:偏移字节数,大于0,向前偏移,小于0,向后偏移
- whence
- SEEK_SET:文件起始位置
- SEEK_CUR:文件当前读写位置
- SEEK_END:文件末尾
- 解释:文件指针位置加offset个字节,通过whence判断从哪里开始加
-
int fclose(FILE *stream);
- 关闭文件,通过文件指针,并刷新缓冲区
- 成功返回 0,失败返回EOF
系统调用
-
int open(const char *pathname, int flags);
-
int open(const char *pathname, int flags, mode_t mode);
- 对于open函数来说,第三个参数仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于定义文件的访问权限
- S_IRWXU, 700权限,代表该文件所有者具有可读、可写及可执行的权限。
- S_IRUSR或S_IREAD, 400权限,代表该文件所有者具有可读取的权限。
- S_IWUSR或S_IWRITE, 200权限,代表该文件所有者具有可写入的权限。
- S_IXUSR或S_IEXEC, 100权限,代表该文件所有者具有可执行的权限。
- S_IRWXG, 070权限,代表该文件用户组具有可读、可写及可执行的权限。
- S_IRGRP, 040权限,代表该文件用户组具有可读的权限。
- S_IWGRP, 020权限,代表该文件用户组具有可写入的权限。
- S_IXGRP, 010权限,代表该文件用户组具有可执行的权限。
- S_IRWX, 007权限,代表其他用户具有可读、可写及可执行的权限。
- S_IROTH, 004权限,代表其他用户具有可读的权限
- S_IWOTH, 002权限,代表其他用户具有可写入的权限。
- S_IXOTH, 001权限,代表其他用户具有可执行的权限。
- flags 用于指定文件的打开/创建模式,这个参数可由以下常量(定义于fcntl.h)通过逻辑位或逻辑构成。
- O_RDONLY只读模式
- O_WRONLY只写模式
- O_RDWR读写模式
- 打开/创建文件时,至少得使用上述三个常量中的一个。以下常量是选用的:
- O_APPEND每次写操作都写入文件的末尾
- O_CREAT如果指定文件不存在,则创建这个文件
- O_EXCL如果要创建的文件已存在,则返回-1,并且修改errno的值
- O_TRUNC如果文件存在,并且以只写/读写方式打开,则清空文件全部内容(即将其长度截短为0)
- O_NOCTTY如果路径名指向终端设备,不要把这个设备用作控制终端。
- O_NONBLOCK如果路径名指向FIFO/块文件/字符文件,则把文件的打开和后继I/O
- 返回值:若所有欲核查的权限都通过了检查则返回文件描述符,表示成功,只要有一个权限被禁止则返回-1。
- 对于open函数来说,第三个参数仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于定义文件的访问权限
-
ssize_t read(int fd, void *buf, size_t count);
- 通过fd从文件中读入count个数据存入buf中
- 如果顺利read会返回实际读入的字节数。当有错误发生时则返回-1,错误代码存入errno中。
-
ssize_t write(int fd, const void *buf, size_t count);
- 将buf中的count个数据写到fd指向的文件中
- 如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。
-
off_t lseek(int fd, off_t offset, int whence);
- 和fseek类似
- lseek 的以下用法返回当前的偏移量
- 对于普通文件(regular file),cfo 是一个非负整数。但对于特殊设备,cfo 有可能是负数。因此,我们不能简单地测试 lseek 的返回值是否小于 0 来判断 lseek 成功与否,而应该测试 lseek 的返回值是否等于 -1 来判断 lseek 成功与否。
- lseek 仅将 cfo 保存于内核中,不会导致任何 I/O 操作。这个 cfo 将被用于之后的读写操作。
- 如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。
内存映射
-
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
- mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零
- addr:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。
- length:映射区的长度。//长度单位是 以字节为单位,不足一内存页按一内存页处理
- prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
- PROT_EXEC //页内容可以被执行
- PROT_READ //页内容可以被读取
- PROT_WRITE //页可以被写入
- PROT_NONE //页不可访问
- flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
- MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
- MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
- MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
- MAP_DENYWRITE //这个标志被忽略。
- MAP_EXECUTABLE //同上
- MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
- MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
- MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
- MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
- MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
- MAP_FILE //兼容标志,被忽略。
- MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持。
- MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
- MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。
- fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时需要指定flags参数中的MAP_ANON,表明进行的是匿名映射。
- off_toffset:被映射对象内容的起点。
- Rreturn:
- mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1
-
int munmap(void *addr, size_t length);
- 函数说明
- munmap()用来取消参数addr所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。
- 函数说明
-
int msync ( void * addr, size_t len, int flags)
- addr:文件映射到进程空间的地址;
- len:映射空间的大小;
- flags:刷新的参数设置
- 取值为MS_ASYNC(异步)时,调用会立即返回,不等到更新的完成;
- 取值为MS_SYNC(同步)时,调用会等到更新完成之后返回;
- 取MS_INVALIDATE(通知使用该共享区域的进程,数据已经改变)时,在共享内容更改之后,使得文件的其他映射失效,从而使得共享该文件的其他进程去重新获取最新值;
- return:
- 成功则返回0;失败则返回-1;
目录操作
-
DIR* opendir (const char * path );
- 功能:打开一个目录,在失败的时候返回一个空的指针。
-
struct dirent* readdir(DIR* dir_handle);
- 每次读取一个文件
- 本函数用来读取目录。返回是dirent结构体指针,dirent结构体成员如下,
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen;/* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1];/* file name (null-terminated) 文件名,最长255字符 */
}
- int closedir(DIR *dir);
- closedir()关闭参数dir所指的目录流。关闭成功则返回0,失败返回-1,错误原因存于errno 中。EBADF 参数dir为无效的目录流。
进程函数
进程创建
- pid_t fork( void);
- 返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
- 子进程在创建时会复制父进程的代码段和各种环境,pid不同,所以对于父进程和子进程,fork返回不同的值
进程等待
-
pid_t wait (int * status);
-
参数 status 是一个整形指针。如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中。如果不关心终止状态,可以将 status参数设置为NULL。
-
status 不是NULL时子进程的结束状态值会由参数 status 返回,而子进程的进程识别码作为函数返回值返回。
-
调用 wait 函数时,调用进程将会出现下面的情况:
- 如果其所有子进程都还在运行,则阻塞。
- 如果一个子进程已经终止,正等待父进程获取其终止状态,则获取该子进程的终止状态然后立即返回。
- 如果没有任何子进程,则立即出错返回
-
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。
-
pid_t waitpid(pid_t pid,int * status,int options);
- 如果在调用 waitpid()时子进程已经结束,则 waitpid()会立即返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数 status 可以设成 NULL
- 参数 pid 为欲等待的子进程识别码,
- pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
- pid=-1 等待任何子进程,相当于 wait()。
- pid=0 等待进程组识别码与目前进程相同的任何子进程。
- pid>0 等待任何子进程识别码为 pid 的子进程。
- 参数options提供了一些额外的选项来控制waitpid,参数 option 可以为 0 或可以用"|"运算符把它们连接起来使用,比如:ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);如果我们不想使用它们,也可以把options设为0,如:ret=waitpid(-1,NULL,0);
- WNOHANG 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。
- WUNTRACED 若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会。WIFSTOPPED(status)宏确定返回值是否对应与一个暂停子进程。
- 子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:
- WIFEXITED(status)如果若为正常结束子进程返回的状态,则为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位。
- WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
- WIFSIGNALED(status)若为异常结束子进程返回的状态,则为真;对于这种情况可执行WTERMSIG(status),取使子进程结束的信号编号。
- WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
- WIFSTOPPED(status) 若为当前暂停子进程返回的状态,则为真;对于这种情况可执行WSTOPSIG(status),取使子进程暂停的信号编号。
- WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
- 如果执行成功则返回子进程识别码(PID) ,如果有错误发生则返回,返回值-1。失败原因存于 errno 中。
exec系统族
说是exec系统调用,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:
- int execl(const char *path, const char *arg, …);
- int execlp(const char *file, const char *arg, …);
- int execle(const char *path, const char *arg, …, char * const envp[]);
- int execv(const char *path, char *const argv[]);
- int execvp(const char *file, char *const argv[]);
- int execve(const char *path, char *const argv[], char *const envp[]);
其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
execve
- 第1个参数path是被执行应用程序的完整路径
- 第2个参数argv就是传给被执行应用程序的命令行参数
- 第3个参数envp是传给被执行应用程序的环境变量。
- 在这里有点要注意,不管是arg0,还是argv[0]都必须是程序的可执行文件的名字
- execl("/bin/echo", “echo”, “executed by execl”, NULL)中的echo;
- execl("/bin/ls", “ls”, “/azuo”, “-la”, (char *)0 )中的ls;
- execlp(“echo”, “echo”, “executed by execlp”, NULL)中的echo;
- 留心看一下这6个函数还可以发现,前3个函数都是以execl开头的,后3个都是以execv开头的,它们的区别在于,execv开头的函数是以"char *argv[]"这样的形式传递命令行参数,而execl开头的函数采用了我们更容易习惯的方式,把参数一个一个列出来,然后以一个NULL表示结束。这里的NULL的作用和argv数组里的NULL作用是一样的。
这里建议使用 (char *)0 代替NULL。 - 在全部6个函数中,只有execle和execve使用了char *envp[]传递环境变量,其它的4个函数都没有这个参数,这并不意味着它们不传递环境变量,这4个函数将把默认的环境变量不做任何修改地传给被执行的应用程序。而execle和execve会用指定的环境变量去替代默认的那些。
- 还有2个以p结尾的函数execlp和execvp,咋看起来,它们和execl与execv的差别很小,事实也确是如此,除execlp和 execvp之外的4个函数都要求,它们的第1个参数path必须是一个完整的路径,如"/bin/ls";而execlp和execvp的第1个参数 file可以简单到仅仅是一个文件名,如 “ls”,这两个函数可以自动到环境变量PATH制定的目录里去寻找。
信号
-
sig_t signal(int signum,sig_t handler);
- 第一个参数signum指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
- 第二个参数handler描述了与信号关联的动作,它可以取以下三种值:
- 一个无返回值的函数地址
- 此函数必须在signal()被调用前申明,handler中为这个函数的名字。当接收到一个类型为signum的信号时,就执行handler 所指定的函数。这个函数应有如下形式的定义:void func(int sig);
- SIG_IGN 这个符号表示忽略该信号,执行了相应的signal()调用后,进程会忽略类型为sig的信号。
- SIG_DFL 这个符号表示恢复系统对信号的默认处理。
- 一个无返回值的函数地址
- 返回先前的信号处理函数指针,如果有错误则返回SIG_ERR(-1)。
-
int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
-
函数说明 sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
信号处理函数可以采用
- void (*sa_handler)(int)
- void (*sa_sigaction)(int, siginfo_t *, void *)
到底采用哪个要看sa_flags中是否设置了SA_SIGINFO位,如果设置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此时可以向处理函数发送附加信息;默认情况下采用void (*sa_handler)(int),此时只能向处理函数发送信号的数值。
-
sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。
-
sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号集搁置。
-
sa_flags 成员用于指定信号处理的行为,它可以是一下值的“按位或”组合。
- SA_RESTART:使被信号打断的系统调用自动重新发起。
- SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
- SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
- SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
- SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
- SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。
-
re_restorer 成员则是一个已经废弃的数据域,不要使用。
-
管道
-
int pipe(int fd[2])
- 该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
- 管道的读写规则
- 管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。
-
int dup(int fd);
-
int dup2(int fd1,int fd2);
- 两个均为复制一个现存的文件的描述
- 两个函数的返回:若成功为新的文件描述,若出错为-1;
- 由dup返回的新文件描述符一定是当前可用文件描述中的最小数值。用dup2则可以用fd2参数指定新的描述符数值。如果fd2已经打开,则先关闭。若fd1=fd2,则dup2返回fd2,而不关闭它。通常使用这两个系统调用来重定向一个打开的文件描述符。
线程
- int pthread_create(pthread_t *tidp,const pthread_attr_t attr,(void)(start_rtn)(void),void *arg);
- int pthread_join(pthread_t thread, void **retval);
- void pthread_exit(void* retval);
- int sem_init(sem_t *sem, int pshared, unsigned int value);
- int sem_wait(sem_t * sem);
- int sem_post(sem_t *sem);
- int sem_destroy(sem_t *sem);
IPC
- int msgget(key_t key, int msgflg);
- 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);
- int msgctl(int msqid,int cmd,struct msqid_ds *buf)
- int semget(key_t key,int nsems,int semflg);
- int semctl(int semid,int semnum,int cmd, /union semun arg/);
- int semop(int semid,struct sembuf *sops,size_t nsops);
- 共享内存
socket
本文仅用于个人Linux复习整理,内容来自于百度百科和Linux man手册