函数结构
头文件:
函数声明:
功能:
参数:
返回值:
成功:
失败:
使用注意事项:
标准IO
定义在C库中的用于输入输出的函数接口
fopen
头文件:
# include <stdio.h>
函数声明
FILE *fopen(const char *path, const char *mode);
功能: 打开文件
参数:
const char *path:打开文件的路径
const char *mode:文件打开方式
返回值:
成功:返回文件流指针
失败:返回NULL,更新errno
使用注意事项:
- mode打开方式
打开方式 | 权限 | 功能 |
---|---|---|
r | 只读 | 文件指针定位到文件开头(有文件) |
r+ | 可读可写 | 文件指针定位到文件开头(有文件) |
w | 只写 | 文件不存在则创建,文件存在则清空, 文件指针定位到文件开头 |
w+ | 可读可写 | 文件不存在则创建,文件存在则清空, 文件指针定位到文件开头 |
a | 只写 | 文件不存在则创建,文件存在则追加, 文件指针定位到文件末尾 |
a+ | 可读可写 | 文件不存在则创建,文件存在则追加, 文件指针定位到文件末尾 |
- 打开文件是有限资源,最多打开1024个文件,所以操作完文件要及时关闭
fclose
头文件:
#include <stdio.h>
函数声明:
int fclose(FILE *stream);
功能: 关闭文件
参数: 文件流指针
返回值:
成功:返回0
失败:返回EOF,更新errno
fgetc
头文件:
#include <stdio.h>
函数声明:
int fgetc(FILE *stream);
功能: 从文件中读取一个字符
参数: 流指针,指向目标文件
返回值:
成功:返回读取到的字符的ASCII,读取到文件末尾返回-1
失败:返回EOF
fputc
头文件:
#include <stdio.h>
函数声明:
int fputc(int c, FILE *stream);
功能: 向文件中输入一个字符
参数:
int c:输入字符的ASCII
FILE *stream:文件流指针,指向目标文件
返回值:
成功:写入字符的ASCII
失败:返回EOF,更新errno
fgets
头文件:
#include <stido.h>
函数声明:
char *fgets(char *s, int size, FILE *stream);
功能: 从文件中获取一定长度的字符串
参数:
char *s:从文件中获取的字符串存放的首地址
int size:从文件中获取的字符串的长度
FILE *stream:流指针,指向目标文件
返回值:
成功:返回读获取的字符串的首地址,读到文件结尾会返回NULL
失败:返回NULL
使用注意事项:
- fgets获取到字符串之后会自动补’\0’,所以实际获取的字符个数为size-1
- 文件中不满size-1个字符,有多少字符读多少字符,最后自动补’\0’
- 当读取到’\n’时,停止读取内容,再次调用fgets之后从下一行起始位置开始继续读取
fputs
头文件:
#include <stdio.h>
函数声明:
int fputs(const char *s, FILE *stream);
功能: 向文件中写入一定长度的字符串
参数:
const char *s:向文件中写入的字符串首地址
FILE *stream:流指针,指向目标文件
返回值:
成功:输入字符个数
失败:返回EOF
fread
头文件:
#include <stdio.h>
函数声明:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能: 从指定文件中读取内容
参数:
void *ptr
:存放读取内容的首地址
size_t size
:读取一个数据元素的字节大小,一次读多少字节
size_t nmemb
:读取的元素个数
FILE *stream
:流指针,指向目标文件
返回值:
成功:读取到的文件个数,读到文件末尾返回0
失败:返回EOF
fwrtie
头文件:
#include <stdio.h>
函数声明:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能: 向文件中写入内容
参数:
void *ptr:向文件中写入内容的首地址
size_t size:写入的一个数据元素的字节大小,一次写多少字节
size_t nmemb:写入的元素个数
FILE *stream:流指针,指向目标文件
返回值:
成功:返回写入数据元素的个数
失败:返回EOF
rewind
头文件:
#incldue <stdio.h>
函数声明:
void rewind (FILE *stream);
功能: 将文件指针移动到文件开头
参数: FILE *stream:流指针,指向目标文件
返回值: 空
ftell
头文件:
#include <stdio.h>
函数声明:
long ftell(FILE *stream);
功能: 计算文件指针相对于文件开头的字节数
参数: FILE *stream:流指针,指向目标文件
返回值:
成功:返回文件指针所在位置
失败:返回EOF,更新errno
fseek
头文件:
#include <stdio.h>
函数声明:
int fseek(FILE *stream, long offset, int whence);
功能: 偏移文件指针的位置
参数:
FILE *stream:目标文件
long offset:偏移量,向后为正方向
int whence:相对位置
返回值:
成功:返回0
失败:返回EOF,更新errno
使用注意事项:
宏名 | 相对位置 |
---|---|
SEEK_SET | 文件开头 |
SEEK_CUR | 当前位置 |
SEEK_END | 文件结尾 |
fflush
头文件:
#include <stdio.h>
函数声明:
int fflush(FILE* stream);
功能: 强制刷新缓存区
参数: FILE* stream:指向文件,NULL时刷新所有流
返回值:
成功:返回0
失败:返回EOF,更新errno
fprintf
头文件:
#include <stdio.h>
函数声明:
int fprintf(FILE *stream, const char *format, ...);
功能: 向指定文件中以指定格式写入数据
参数:
FILE *stream:流指针,指向目标文件
const char *format:指定的格式
……:多个参数
返回值:
成功:返回输出字符个数
失败:返回EOF
使用注意事项: 用法上同printf
,只是多了一个指向文件的指针
perror
头文件:
#include <stdio.h>
函数声明:
void perror(const char *s);
功能: 根据errno获取错误信息,将信息输出到终端
参数: const char *s:提示内容
返回值: 无
文件IO
文件IO用到的头文件
- 纯享版
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
头文件对应的函数
#include <sys/types.h> // open/lseek
#include <sys/stat.h> // open
#include <fcntl.h> // open
#include <unistd.h> // close/read/write/lseek
open
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数声明:
int open(const char *pathname, int flags);
功能: 打开文件
参数:
const char *pathname:文件路径
int flags:打开方式
返回值:
成功:返回文件描述符
失败:返回EOF
使用注意事项:
- 文件打开方式对应的操作
文件打开方式 | 对应权限 |
---|---|
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 可读可写 |
O_CREAT | 创建 |
O_TRUNC | 清空 |
O_APPEND | 追加 |
- 当参数
int flags
为O_CREAT(创建)时,函数定义改变
int open(const char *pathname, int flags, mode_t mode);
mode:创建文件的权限,权限的算法:mode &~umask
umask:文件权限掩码,值为0002
权限掩码修改:查看权限掩码:umask 修改文件权限掩码:umask 0000 修改后的权限掩码可以与mode保持一致
close
头文件:
#include <unistd.h>
函数声明:
int close(int fd);
功能: 关闭文件
参数: 文件描述符
返回值:
成功:0
失败:-1
read
头文件:
#include <unistd.h>
函数声明:
ssize_t read(int fd, void *buf, size_t count);
功能: 读文件
参数:
int fd:文件描述符
void *buf:存放内容的首地址
size_t count:期待读取的字符个数
返回值:
成功:返回实际读取到的字符个数,读到文件结尾返回0
失败:返回EOF,更新errno
使用注意事项:
- read读文件时count是多少就读多少,不会自动补‘\0’,遇到\n也不会自动停止,会继续读取下一行的内容。所以在使用时,需要人为预留下\0的位置
- 通过返回值作为实际读到的字符个数
char *buf[32] = {};
ssizeo_t ret = read(fd,buf,31);
buf[ret] = '\0';
- 每次读取到的内容放到数组之前先清空数组
memset(buf, 0, sizeof(char)*32);
bzero(buf, sizeof(char)*32);
write
头文件:
#include <unistd.h>
函数声明:
ssize_t write(int fd, const void *buf, size_t count);
功能: 写文件
参数:
int fd:文件描述符
void *buf:写入内容的首地址
size_t count:期待写入的字符个数
返回值:
成功:返回实际写入的字符个数
失败:失败返回EOF,并更新errno
使用注意事项: “ 读多少写多少 “ 代码模型
ssize_t ret = read(fd1, buf, 64);
write(fd2, buf, ret);
数组不需要清空,也不需要预留 ’ \0 ’ 的位置
lseek
头文件:
#include <sys/types.h>
#include <unistd.h>
函数声明:
off_t lseek(int fd, off_t offset, int whence);
功能: 将文件指针偏移到指定位置
参数:
fd:文件描述符
offset:偏移量:向后为正方向
whence:相对位置
返回值:
成功:返回基于文件开头的当前位置,即文件长度,单位为字节
失败:返回EOF,更新errno
使用注意事项:
宏名 | 相对位置 |
---|---|
SEEK_SET | 文件开头 |
SEEK_CUR | 当前位置 |
SEEK_END | 文件结尾 |
目录IO
目录IO用到的头文件
- 纯享版
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
- 头文件对应的函数
#include <sys/types.h> // opendir/closedir/stat
#include <dirent.h> // opendir/closedir/readdir
#include <unistd.h> // chdir/stat
#include <sys/stat.h> // stat
opendir
头文件:
#include <sys/types.h>
#include <dirent.h>
函数声明:
DIR *opendir(const char *name);
功能: 打开目录文件
参数: 目录流,指向打开的目录文件
返回值:
成功:返回目录流指针
失败:返回NULL,更新errno
closedir
头文件:
#include <sysy/types.h>
#include <dirent.h>
函数声明:
int closedir(DIR *dirp);
功能: 关闭目录文件
参数: 目录流,指向打开的目录文件
返回值:
成功:返回0
失败:返回EOF,更新errno
readdir
头文件:
#include <dirent.h>
函数声明:
struct dirent *readdir(DIR *dirp);
功能: 读取目录文件内容
参数: 目录流,指向打开的目录文件
返回值:
成功:返回结构体指针,读到文件结尾返回NULL
失败:返回NULL
使用注意事项:
结构体
struct dirent
{
ino_t dino; // 文件的inode
off_t d_off;
unsigned short d_reclen;
unsigned char d_type; //文件类型,并不支持所有文件类型
char d_name[256]; // 文件名
};
chdir
头文件:
#include <unistd.h>
函数声明:
int chdir(const char* path);
功能: 改变当前的工作路径
参数: const char* path:修改之后的路径
返回值:
成功:返回0
失败:返回EOF,更新errno
使用注意事项:
- 只有程序走到该函数之后,工作路径才会改变,后续的操作都是在修改之后的路径下实现的
stat
头文件:
#include <sysy/types.h>
#include <sys/stat.h>
#include <unistd.h>
函数声明:
int stat(const char *pathname, struct stat *buf);
功能: 获取文件属性
参数:
const char *pathname:文件
struct stat *buf:获取到属性存放的位置
返回值:
成功:返回0
失败:返回EOF,更新errno
使用注意事项:
buf的结构体内容如下
struct stat
{
dev_t st_dev; // 包含文件的设备ID
ino_t st_ino; // 文件的inode号
mode_t st_mode; // 文件的类型和权限
nlink_t st_nlink; // 硬链接数
uid_t st_uid; // 用户ID
gid_t st_gid; // 组ID
dev_t st_rdev;
off_t st_size; //大小
blksize_t st_blksize; // 文件系统IO块的大小
blkcnt_t st_blocks; // 512b的分配数量
struct timespec st_atim; // 最后一次访问的时间
struct timespec st_mtim; // 最后一次修改的时间
struct timespec st_ctim; // 最后一次状态改变的时间
}
- 基本用法
获取文件的inode号
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main()
{
// 定义变量
DIR* dirp = NULL;
struct stat sb = {};
struct dirent *dir = NULL;
// 打开文件
dirp = opendir("./");
if(dirp == NULL)
{
perror("opendir err");
return EOF;
}
// 读取文件
dir = readdir(dirp);
// stat获取inode号
stat(dir->name, &sb);
printf("%s inode is %ld\n", dir->name, sb->st_ino);
closedir(dirp);
return 0;
}
- 获取文件类型
查询 man 7 inode可以得到对于文件类型定义了以下8进制掩码
宏名 | 掩码值 | 文件类型 |
---|---|---|
S_IFMT | 0170000 | 判断文件类型 |
S_IFSOCK | 0140000 | socket—套接字 |
S_IFLNK | 0120000 | symbolic link—连接文件 |
S_IFREG | 0100000 | regular file —普通文件 |
S_IFBLK | 0060000 | block device — 块设备文件 |
S_IFDIR | 0040000 | directory — 目录文件 |
S_IFCHR | 0020000 | character—字符设备文件 |
S_IFIFO | 0010000 | FIFO—管道文件 |
- 先通过stat获取8进制的mode
stat(dir->name, &sb);
printf("mode is %o",sb.st_mode);
- 掩码的使用
if((sb.st_mode & S_IFMT) == S_IFREG)
printf("普通文件");
- man手册里还写了另一种宏名写法
宏名 | 判断文件类型 |
---|---|
S_ISREG(mode) | regular file—普通文件 |
S_ISDIR(mode) | directory—目录文件 |
S_ISCHR(mode) | character device—字符设备文件 |
S_ISBLK(mode) | block device—块设备文件 |
S_ISFIFO(mode) | FIFO—管道文件 |
S_ISLNK(mode) | symbolic link—连接文件 |
S_ISSOCK(mode) | socket—套接字文件 |
if(S_ISREG(sb.st_mode))
printf("regular file\n");
- 获取文件权限
对于文件权限,也有相应的掩码
宏名 | 掩码 | 权限 |
---|---|---|
S_IRUSR | 00400 | 用户的读权限 |
S_IWUSR | 00200 | 用户的写权限 |
S_IXUSR | 00100 | 用户的执行权限 |
S_IRGRP | 00040 | 同组的读权限 |
S_IWGRP | 00020 | 同组的写权限 |
S_IXGRP | 00010 | 同组的执行权限 |
S_IROTH | 00004 | 其他用户的读权限 |
S_IWOTH | 00002 | 其他用户的写权限 |
S_IXOTH | 00001 | 其他用户的执行权限 |
if(sb.st_mode & S_IRUSR)
printf("r");
- 其他结构体成员的使用
- 通过用户ID获取用户名
struct passwd* user_name = NULL;
user_name = getpwuid(sb.st_uid);
user_name->pw_name;
- 通过组ID获取组名
struct group* gig_name = NULL;
gig_name = getgrgid(sb.st_gid);
gig_name->gr_name;
- 转换时间格式
ctime(sb.st_mtim);
// 将时间转换成为"Wed Jun 30 21:49:08 1993\n"的固定格式
getpwuid
头文件:
#include <pwd.h>
函数声明:
struct passwd* getpwuid(uid_t uid);
功能: 获取用户信息
参数: uid_t uid:用户ID
返回值:
成功:返回结构体地址
失败:NULL
使用注意事项:
用户信息结构体
struct passwd
{
char *pw_name; // 用户名
char *pw_passwd; // 用户密码
uid_t pw_uid; // 用户ID
gid_t pw_gid; // 组ID
char *pw_gecos; // 用户信息
char *pw_dir; // 家目录
char *pw_shell;
};
getgrgid
头文件:
#include <grp.h>
函数声明:
struct group *getgrgid(gid_t gid);
功能: 获取组信息
参数: gid_t gid:组ID
返回值:
成功:返回结构体地址
失败:NULL
使用注意事项:
组信息结构体
struct group
{
char *gr_name; // 组名
char *gr_passwd; // 组密码
gid_t gr_gid; // 组ID
char **gr_mem; // 组内成员
};
时间
time
头文件:
#include <time.h>
函数声明:
time_t time(time_t *tloc);
功能: 获取1970-01-01 00:00:00到现在的秒数
参数: time_t *tloc:获取到的时间的地址
返回值:
成功:返回获取到的时间
失败:返回EOF
使用注意事项: 返回的是秒数,是一个很大的int类型的数据
localtime
头文件:
#include <time.h>
函数声明:
struct tm *localtime(const time_t *timep);
功能: 将time获取的时间转换成结构体中的格式
参数: const time_t *timep:保存时间变量的地址
返回值:
成功:返回结构体地址
失败:返回NULL
使用注意事项:
- localtime的结构体定义如下
struct tm
{
int tm_sec; // seconds(0-60)秒
int tm_min; // minutes(0-59)分钟
int tm_hour; // Hours(0-23)小时
int tm_yday; // day in the year(0-365, 1 Jan = 0)天数
int tm_wday; // day in the week (0-6, sunday = 0)周
int tm_mday; // day in the month (1-31)日期
int tm_mon; // month(0-11)月份
int tm_year; // year-1900年份
}
- 年份在计算时-掉了1900,所以在输出的时候要+1900
ctime
头文件:
#include <time.h>
函数声明:
char *ctime(const time_t *timep);
功能: 将时间转换成固定格式
参数: const time_t *timep:保存时间变量的地址
返回值:
成功:返回转换后地址
失败:返回NULL
使用注意事项:
将时间转换成为"Wed Jun 30 21:49:08 1993\n"的固定格式
进程函数
fork和vfork
头文件
#include <sys/types.h>
#include <unistd.h>
函数声明
pid_t fork(void);
pid_t vfork(void);
功能: 创建子进程
参数: 无
返回值:
成功:父进程返回PID,子进程返回0
失败:父进程返回-1,更新errno
注意事项
- fork创建子进程的特点
1)fork 创建一个子进程,父进程返回子进程的PID,子进程返回0.
2)fork 创建则子进程几乎拷贝了父进程的所有内容,fork 之前的代码被复制但不被执行,fork 之后的代码被复制被执行。
3)fork 创建进程一旦成功,进程之间相互独立,各自分配0-4g的虚拟内存空间。
4)fork 创建进程之前打开的文件可以通过复制拿到同一个文件描述符(文件指针),父子进程可以操作同一个文件。
5)如果父进程退出,子进程没有退出,子进程会变成孤儿进程,被init进程收养,然后孤儿进程变成后台进程;子进程退出,父进程没有及时收回子进程的资源,子进程变成僵尸进程。 - fork与vfork的区别
fork() | vfork() | |
---|---|---|
数据 | 子进程拷贝父进程的数据段,代码段 | 子进程与父进程共享数据段 |
执行 | 父子进程之间执行次序不确定 | 保证子进程先运行,在子进程调用exec()或exit()之后,父进程才能运行 |
使用 | 更通用,适用于需要创建一个完全独立的子进程的场景 | 适用于子进程立即执行exec()覆盖自身的场景,可以避免不必要的地址空间复制,提高性能 |
- fork创建的子进程会复制父进程缓存区的内容
wait
头文件
#include <sys/types.h>
#include <sys/wait.h>
函数声明
pid_t wait(int *wstatus);
功能: 回收子进程资源
参数: int *wstatus:子进程退出状态,一般为NULL
返回值:
成功:回收的子进程进程号
失败:EOF
注意事项 wait()是阻塞函数,父进程会在这里卡住,等子进程运行结束
waitpid
头文件
#include <sys/types.h>
#include <sys/wait.h>
函数声明
pid_t waitpid(pid_t pid, int *status, int options);
功能: 回收子进程资源
参数:
pid_t pid:子进程进程号
int *status:子进程退出状态,一般为NULL
int options:函数状态的选项
返回值:
成功:返回回收的子进程号,选项为WNOHANG且没有回收子进程时为0
失败:返回EOF
注意事项
- 参数
pid_t pid
有几种不同的情况
pid | 含义 |
---|---|
>0 | 指定子进程进程号 |
= -1 | 任意子进程 |
= 0 | 等待组ID等于调用进程的组ID的任一子进程 |
< -1 | 等待组ID等于pid的绝对值的任一子进程 |
- 参数
int options
的两种选项
1. 0:函数处于阻塞状态,父进程卡住,直到子进程资源被回收
2. WNOHANG:函数处于非阻塞状态,父进程正常运行正常结束,子进程结束后自动回收子进程的资源
exit
头文件
#include <stdlib.h>
函数声明
void exit(int status);
功能: 结束进程,刷新缓存
参数: int status:进程退出的状态
返回值: 空
注意事项
- 参数
int status
为 ‘ 0 ’ 时表示进程正常结束,其他数值表示出现错误,进程非正常结束
_exit
头文件
#include <unistd.h>
函数声明
void _exit(int status);
功能: 结束进程
参数: int stauts:进程结束时的状态
返回值: 空
注意事项
- 参数
int status
为 ‘ 0 ’ 时表示进程正常结束,其他数值表示出现错误,进程非正常结束 exit()
和_exit()
的区别
exit(0); | _exit(0); | |
---|---|---|
缓存 | 刷新缓存区 | 不会刷新缓存区 |
结束进程 | 关闭所有的打开的文件指针 | 立即终止进程 |
getpid和getppid
头文件
#include <sys/types.h>
#include <unistd.h>
函数声明
pid_t getpid(void);
pid_t getppid(void);
功能: 获取当前进程的进程号 / 获取当前进程的父进程的进程号
参数: 无
返回值:
成功:返回当前进程的进程号 / 当前进程的父进程的进程号
失败:返回EOF
exec函数族
作用: 在当前进程中执行一个新进程,旧进程会被新进程完全覆盖,但进程号不变
头文件
#include <unistd.h>
返回值:
成功:不返回
失败:返回EOF,更新error
函数声明
int execl(const char *path, const char *arg, ...
参数:
const char *path
可执行文件的绝对或相对路径
const char *arg
通常是可执行文件名,参数列表以NULL结尾
int execlp(const char *file, const char *arg, ...
类似 execl,但 file 只需要是可执行文件的名称,函数会根据环境变量 PATH 查找可执行文件的路径。
int execle(const char *path, const char *arg, ...
与 execl 类似,但允许传递一个自定义的环境变量列表 envp。这个环境会代替当前进程的环境变量。
int execv(const char *path, char *const argv[]);
使用路径 path 和参数数组 argv[] 替换当前进程。argv[0] 是程序名,argv[] 数组必须以 NULL 结束。
int execvp(const char *file, char *const argv[]);
类似 execv,但会根据 PATH 环境变量查找可执行文件。
int execvpe(const char *file, char *const argv[],char *const envp[]);
与 execvp 类似,但允许使用自定义的环境变量 envp。
pipe
头文件:
#include <unistd.h>
函数声明:
int pipe(int pipefd[2]);
功能: 创建无名管道
参数: int pipefd[2]
创建的文件描述符,下标为0,1对应两个文件描述符
返回值: 成功返回0,失败返回EOF
使用注意事项:
- 管道中读取空了之后,没有数据时,读取阻塞
char buf[32] = ""; // 写入和读取的地址
// 管道中没有数据时,读取阻塞
read(pipefd[0], buf, 5);
printf("buf = %s\n", buf);
- 管道中写满了数据,写入阻塞,写满:64k,至少读出4k空间才能进行写操作
char full[65536] = ""; // 写满(64k = 65536)
char arr[4096] = ""; // 空出4k空间
// 管道中写满数据时,写入阻塞
write(pipefd[1], full, 65536);
// 读出4k空间
read (pipefd[0], arr, 4096);
printf("write befor\n");
write(pipefd[1], "a", 1);
printf("write after\n");
- 关闭读端,写操作会导致管道破裂,进程结束,收到SIGPIPE
// 关闭读端,写操作会导致管道破裂,进程结束,收到SIGPIPE
close(pipefd[0]);
write(pipefd[1], "a", 1);
printf("write after\n");
mkfifo
头文件:
#include <sys/types.h>
#include <sys/stat.h>
函数声明:
int mkfifo(const char *pathname, mode_t mode);
功能: 创建有名管道
参数:
const char *pathname
管道文件名
mode_t mode
文件权限,8进制数表示0777
返回值: 成功返回0,失败返回EOF,更新errno
使用注意事项:
- 在打开管道时,只有完成读端和写端都打开的操作后,才会完成打开管道文件的操作,否则会在打开管道文件的位置阻塞
- 读写时如果管道内没有数据读操作会阻塞
kill 和 raise
头文件:
#include <sys/types.h>
#include <signal.h>
函数声明:
int kill(pid_t pid, int sig);
int raise(int sig);
功能: 发送信号
kill
发送信号
raise
给自己发信号
参数:
pid_t pid
进程号
int sig
信号
返回值: 成功返回0,失败返回EOF
alarm
头文件:
#include <unistd.h>
函数声明:
unsigned int alarm(unsigned int seconds);
功能: 在进程中定时操作
参数: unsigned int seconds
定时,单位是秒
返回值: 上次设定闹钟的剩余时间
使用注意事项:
第一次调用:返回0
第二次调用:第一次闹钟调用完,到现在调用剩下的时间吗,同时以第二次调用设定的时间为准
signal
头文件:
#include <signal.h>
函数声明:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能: 对信号进行处理
参数:
int signum
信号编号
sighandler_t handler
函数指针,信号的处理方式
返回值:
成功:成功返回设置处理方式之前的处理方式
失败:失败返回EOF
使用注意事项:
- 参数:
sighandler_t handler
信号的处理方式
信号 | 操作 |
---|---|
SIG_IGN | 忽略信号 |
SIG_DFL | 默认操作 |
自定义函数 | 调用函数 |
tfok
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
函数声明:
key_t ftok(const char *pathname, int proj_id);
功能: 生成唯一的 key
参数:
const char *pathname
文件名,只获取inode号
int proj_id
低8位,传一个字符即可
返回值:
成功:成功返回生成的key
失败:失败返回EOF
shmget
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
函数声明:
int shmget(key_t key, size_t size, int shmflg);
功能: 创建或打开共享内存
参数:
key_t key
关键字
size_t size
共享内存的大小
int shmflg
直接使用:IPC_CREAT | IPC_EXCL | 0777
返回值:
成功:成功返回共享内存ID(shmid)
失败:失败返回EOF
使用注意事项:
- 创建成功了之后,打开共享内存,重新获取shmid
shmid = shmget(key, 64, IPC_CREAT | IPC_EXCL | 0777);
if (shmid == EOF)
{
if (errno == EEXIST)
// 创建成功了之后,打开共享内存,重新获取shmid
shmid = shmget(key, 64, 0777);
else
{
perror("shmget err");
return EOF;
}
}
shmat
头文件:
#include <sys/types.h>
#include <sys/shm.h>
函数声明:
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能: 地址映射
参数:
int shmid
共享内存标识,shmid
const void *shmaddr
映射方式,一般为NULL
int shmflg
读写权限
返回值:
成功:成功返回映射后的地址
失败:失败返回(void *)EOF
使用注意事项:
- 使用方式与
malloc
相同,需要强转 - 读写权限:
0
:可读可写
SHM_RDONLY
:只读
shmdt
头文件:
#include <sys/types.h>
#include <sys/shm.h>
函数声明:
int shmdt(const void *shmaddr);
功能: 取消映射
参数: const void *shmaddr
要取消的地址
返回值:
成功:0
失败:EOF
shmctl
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
函数声明:
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
功能: 对共享内存进行各种操作,主要是删除共享内存
参数:
int shmid
共享内存id
int cmd
对共享内存的操作
struct shmid_ds *buf
结构体指针
返回值: 成功返回0,失败返回EOF
使用注意事项:
- 参数:
操作 | 功能 | 结构体指针 |
---|---|---|
IPC_STAT | 获得shmid属性信息 | 存放信息 |
IPC_SET | 设置shmid属性信息 | 设置的属性 |
IPC_RMID | 删除共享内存 | NULL |
线程
pthread_create
头文件:
#include <pthread.h>
函数声明:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
功能:
参数:
pthread_t *thread
线程标识,存放线程ID,传入一个地址(&)
const pthread_attr_t *attr
一般为NULL,线程默认属性
void *(*start_routine) (void*)
线程函数
void *arg
线程函数传递的参数,不传参为NULL
返回值:
成功:0
失败:errno
使用注意事项:
- 参数
void *(*start_routine) (void*)
函数指针,作为线程的执行体,该函数必须是接收void *类型的参数,并返回一个void *类型的值 - CPU调度线程也是随机的
- 编译时加上
-lpthread
- 传参
void *pthreadFun(void *arg)
{
int num = *((int *)arg);
printf("子线程结束\n");
}
int main()
{
int a = 121;
int *p = &a;
}
pthread_exit
头文件:
#include <pthread.h>
函数声明:
void pthread_exit(void *retval);
功能: 退出进程
参数: void *retval
任意类型数据,一般为NULL
返回值: 空
pthread_join
头文件:
#include <pthread.h>
函数声明:
int pthread_join(pthread_t thread, void **retval);
功能: 用于等待一个指定的线程结束,阻塞函数
参数:
pthread_t thread
:创建线程对象
void **retval
:指针*retval指向线程返回的参数,一般是NULL
返回值:
成功:成功返回0
失败:失败errno
pthread_detach
头文件:
#include <pthread.h>
函数声明:
int pthread_detach(pthread_t thread);
功能: 让线程结束时自动回收线程资源,让线程和主线程分离
参数: pthread_t thread
:目标线程
返回值:
成功:成功返回0
失败:失败EOF
使用注意事项:
pthread_self
头文件:
#include <pthread.h>
函数声明:
pthread_t pthread_self(void);
功能: 获取线程号
参数: 无
返回值: 成功:返回线程ID
sem_init
头文件:
#include <semaphore.h>
函数声明:
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能: 初始化信号量
参数:
sem_t *sem
初始化的信号量
int pshared
信号量共享范围(0:线程间,1:进程间)
unsigned int value
信号量的初值
返回值:
成功:成功0
失败:失败EOF
使用注意事项: 一般都设置为0,以便线程的同步
sem_wait
头文件:
#include <semaphore.h>
函数声明:
int sem_wait(sem_t *sem)
功能: 申请资源,p操作
参数: sem_t *sem
信号量
返回值:
成功:成功0
失败:失败EOF
使用注意事项:
函数执行时,信号量大于0,标识有资源可用;信号量为0时,表示没有资源可用,此时程序在此阻塞
sem_post
头文件:
#include <semaphore.h>
函数声明:
int sem_post(sem_t *sem);
功能: 释放资源,V操作
参数: sem_t *sem
信号量
返回值:
成功:成功0
失败:失败EOF
sem_getvalue
头文件:
#include <semaphore.h>
函数声明:
int sem_getvalue(sem_t *sem, int *sval);
功能: 获取信号量的值
参数:
sem_t *sem
信号量对象
int *sval
信号量的值存放的变量(&)
返回值:
成功:成功0
失败:失败errno
sem_destroy
头文件:
#include <semaphore.h>
函数声明:
int sem_destroy(sem_t *sem);
功能: 销毁信号量
参数: sem_t *sem
信号量对象
返回值:
成功:成功返回0
失败:失败errno
pthread_mutex_init
头文件:
#include <pthread.h>
函数声明:
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
功能: 初始化互斥锁
参数:
pthread_mutex_t *mutex
互斥锁
pthread_mutexattr_t *attr
一般为NULL默认属性
返回值: 成功返回0,失败返回EOF
pthread_mutex_lock
头文件:
#include <pthread.h>
函数声明:
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能: 申请互斥锁
参数: pthread_mutex_t *mutex
互斥锁
返回值: 成功返回0,失败返回EOF
pthread_mutex_unlock
头文件:
#include <pthread.h>
函数声明:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能: 释放互斥锁
参数: pthread_mutex_t *mutex
互斥锁
返回值: 成功返回0,失败返回EOF
pthread_mutex_destroy
头文件:
#include <pthread.h>
函数声明:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能: 销毁互斥锁
参数: pthread_mutex_t *mutex
互斥锁
返回值: 成功返回0,失败返回EOF
pthread_cond_init
头文件:
#include <pthread.h>
函数声明:
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
功能: 初始化条件变量
参数:
pthread_cond_t *restrict cond
条件变量对象
const pthread_condattr_t *restrict attr
为NULL,默认变量
返回值: 成功:0 失败:非0
pthread_cond_wait
头文件:
#include <pthread.h>
函数声明:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
功能: 等待信号的产生
参数:
pthread_cond_t *restrict cond
条件变量对象
pthread_mutex_t *restrict mutex
互斥锁
返回值: 成功:0 失败:非0
使用注意事项:
- 没有信号的时候函数会阻塞,同时解锁;等到条件产生,函数会结束结束阻塞同时上锁
pthread_cond_signal
头文件:
#include <pthread.h>
函数声明:
int pthread_cond_signal(pthread_cond_t *cond);
功能: 产生条件变量信号
参数: pthread_cond_t *cond
条件变量
返回值: 成功:0,失败:非0
使用注意事项:
- 一定要pthread_cond_wait先执行,再产生条件
pthread_cond_destroy
头文件:
#include <pthread.h>
函数声明:
int pthread_cond_destroy(pthread_cond_t *cond);
功能: 将条件变量销毁
参数: pthread_cond_t *cond
条件变量
返回值: 成功:0,失败:非0