Linux应用常用接口
- 文件IO
- 标准IO库
- 格式化I/O
- 文件I/O的内核缓冲
- 直接I/O绕过内核缓冲
- stdio缓冲(应用)
- 文件描述符与FILE指针互转
- 文件属性与目录
- 用户属主
- 文件访问权限
- 文件时间属性
- 创建链接文件
- 目录
- 字符串处理
- 字符串输出:putchar()
- puts()
- fputc()
- fputs()
- 字符串输入:gets()
- getchar()
- fgets()
- fgetc()
- 字符串拼接:strcat()
- strncat()
- 字符串拷贝:strcpy()
- strncpy()
- 内存填充:memset()
- bzero
- 字符串比较:strcmp()
- strncmp()
- 字符串查找:strchr()
- strrchr()
- strstr()
- 字符串转整形数据:atoi()
- 字符串转整形数据:atol()
- 字符串转整形数据:atoll()
- strtol()
- strtoll()
- strtoul()
- strtoull()
- atof()
- strtof() strtod() strtold()
- 系统信息与资源
- 信号
- 进程
文件IO
本文旨在记录一些Linux应用开发的接口,方便查询使用。
打开文件:open()
函数原型:
int open(const char *pathname, int oflag, ... /* mode_t mode */);
参数描述:
const char *pathname:要打开文件的路径
int oflag:打开文件需要的标志
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件。
上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
O_EXCL 如果O_CREAT 也被设置,此指令会去检查文件是否存在。文件若不存在则建立该文件,否则将导致打开文件错误。此外,若O_CREAT与O_EXCL同时设置,并且欲打开的文件为符号连接,则会打开文件失败。
O_NOCTTY 如果欲打开的文件为终端机设备时,则不会将该终端机当成进程控制终端机。
O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的 资料也会消失。
O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。
O_NONBLOCK 以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。
O_NDELAY 同O_NONBLOCK。
O_SYNC 以同步的方式打开文件。
O_NOFOLLOW 如果参数pathname 所指的文件为一符号连接,则会令打开文件失败。
O_DIRECTORY 如果参数pathname 所指的文件并非为一目录,则会令打开文件失败。
O_DSYNC 使得每个write()调用都会将文件数据写入磁盘,相当于调用fdatasync()
O_SYNC 使得每个write()调用都会自动将文件元数据和内容数据写入磁盘,相当于调用sync()
返回值:
成功:返回已打开文件的fd
失败:返回-1
代码示例:
写文件:write()
函数原型:
ssize_t write(int fd, connst void *buf, size_t count);
参数描述:
int fd:目标文件
connst void *buf:存放要写入的数据
size_t count:写入的字节大小
返回值:
成功:返回实际写入的字节数
失败:返回-1
代码示例:
读文件:read()
函数原型:
ssize_t read(int fd, void *buf, size_t count);
参数描述:
int fd:目标文件
connst void *buf:存放读取到的数据
size_t count:读取的字节大小
返回值:
成功:返回实际读取的字节数
失败:返回-1
代码示例:
关闭文件:close()
函数原型:
int close(int fd);
参数描述:
int fd:目标文件
返回值:
成功:返回 0
失败:返回-1
代码示例:
/*头文件自行man查询*/
int main(void)
{
int fd;
int ret;
/*如果文件不存在就创建*/
fd = open("./test", O_WRONLY | O_CREAT, 0644);
if(-1 == fd)
{
printf("open error\n");
return 1;
}
/*写入字节*/
ret = write(fd, "hello world", 11);
if(-1 == ret)
{
printf("write error\n");
close(fd);
return 1;
}
close(fd);
return 0;
}
读写位置偏移:lseek()
函数原型:
off_t lseek(int fd, off_t offset, int whence);
参数描述:
int fd:目标文件
off_t offset:偏移量
正数:正向偏移
负数:负向偏移
int whence:参考值
SEEK_SET:文件头部
SEEK_CUR:文件指针当前位置
SEEK_END:文件尾部
返回值:
成功:返回从文件头部开始偏移的偏移量
失败:返回-1
代码示例:
错误编号errno
errno变量:全局变量
strerror(errno):返回错误信息
perror(char *str):打印错误信息
复制文件描述符:dup()
复制出来的文件描述符和原文件描述符指向同一个文件表
函数原型:
int dup(int oldfd);
参数描述:
int oldfd:原有的文件描述符
返回值:
成功:新的文件描述符
失败:返回-1
代码示例:
int main(void)
{
int fd1, fd2;
int ret;
char buf[128] = {0};
fd1 = open("./test", O_RDWR | O_CREAT);
if (-1 == fd1)
{
perror("open error");
return 1;
}
fd2 = dup(fd1);
if(-1 == fd2)
{
perror("dup error");
close(fd1);
return 1;
}
ret = write(fd2, "hello world", 11);
if(-1 == ret)
{
perror("write error");
close(fd1);
close(fd2);
return 1;
}
lseek(fd1, 0, SEEK_SET);
ret = read(fd1, buf, 11);
if(-1 == ret)
{
perror("read error");
close(fd1);
close(fd2);
return 1;
}
printf("read:%s\n", buf);
close(fd1);
close(fd2);
return 0;
}
dup2()
允许用户指定newfd的大小
函数原型:
int dup2(int oldfd, int newfd);
参数描述:
int oldfd:原有的文件描述符
int newfd:新的文件描述符(可以自己指定,如果被占用,系统会自动往后找可用的文件描述符)
返回值:
成功:返回newfd
失败:返回-1
代码示例:
原子读写:pread()
用于读取指定偏移位置的数据
函数原型:
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
参数描述:
int fd:目标文件
connst void *buf:存放要读取的数据
size_t count:写入的字节大小
off_t offset:偏移量
返回值:
成功:返回实际读取的字节数
失败:返回-1
代码示例:
原子读写:pwrite()
读写指针不会被更新
用于写入指定偏移位置的数据
函数原型:
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
参数描述:
int fd:目标文件
connst void *buf:存放要写入的数据
size_t count:写入的字节大小
off_t offset:偏移量
返回值:
成功:返回写入的字节数
失败:返回-1
代码示例:
截断文件:truncate()
函数原型:
int truncate(const char *path, off_t length);
参数:
const char *path:文件路径
off_t length:截断长度
返回值:
成功返回0
失败返回-1 设置errno
ftruncate()
函数原型:
int ftruncate(int fd, off_t length);
参数:
int fd:文件描述符
off_t length:截断长度
返回值:
成功返回0
失败返回-1 设置errno
控制文件描述符:fcntl()
函数原型:
int fcntl(int fd, int cmd, .../*arg*/);
参数:
int fd:文件描述符
int cmd:操作命令
复制文件描述符(F_DUPFD | F_DUPFD_CLOEXEC)(第三个参数)
获取/设置文件描述符标志(F_GETFD | F_SETFD)只有五个标志可以被设置(O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK)
获取/设置文件状态标志(F_GETFL | F_SETFL)
获取/设置异步IO所有权(F_GETOWN | F_SETOWN)
获取/设置记录锁(F_GETLK | f_SETLK)
返回值:
成功返回文件描述符
失败返回-1 设置errno
ioctl()
函数原型:
int ioctl(int fd, unsigned long request, ...);
参数:
int fd:文件描述符
unsigned long request:与具体的操作对象有关
返回值
成功返回0
失败返回-1
标准IO库
打开文件:fopen()
函数原型:
FILE *fopen(const char *path, const char *mode);
参数:
const char *path:文件路径
const char *mode:打开文件的权限
r:只读
r+:可读可写
w:只写 文件存在则截断 文件不存在则创建
w+:可读可写 文件存在则截断 文件不存在则创建
a:只写 追加
a+:可读可写 追加
默认权限0666
返回值
成功返回FILE指针
关闭文件:fclose()
函数原型:
int fclose(FILE *stream);
参数:
FILE *stream:文件句柄
返回值:
读文件:fread()
函数原型:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
void *ptr:缓冲区
size_t size:每个数据项的字节大小
size_t nmemb:数据项
FILE *stream:文件句柄
返回值:
成功返回读取到的数据项的数目,如果发生错误或到达文件末尾,则返回值将小于参数nmemb,是否发生错误可以用ferror()或者feof()来判断
写文件:fwrite()
函数原型:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
const void *ptr:缓冲区
size_t size:每个数据项的字节大小
size_t nmemb:数据项
FILE *stream:文件句柄
返回值:
成功返回写入的数据项数目(size乘以nmemb),发生错误返回值将小于参数nmemb(或者等于0)
设置读写位置:fseek()
函数原型:
int fseek(FILE *stream, long offset, int whence);
参数:
FILE *stream:文件句柄
long offset:偏移量
int whence:参考位置
SEEK_SET
SEEK_CUR
SEEK_END
返回值:
成功返回0
失败返回-1 设置errno
判断文件是否到达末尾:feof()
函数原型:
int feof(FILE *stream);
参数:
FILE *stream:文件句柄
返回值:
成功返回0
失败返回非0值 true
判断是否发生错误:ferror()
函数原型:
int ferror(FILE *stream);
参数:
FILE *stream:文件句柄
返回值:
成功返回0
失败返回非0值 true
清楚标志:clearerr()
函数原型:
void clearerr(FILE *stream);
参数:
FILE *stream:文件句柄
返回值:
格式化I/O
格式化输出:printf()
函数原型:
int printf(const char *format, ...);
参数:
const char *format:格式控制字符串
返回值:
fprintf()
将字符串写入到FILE指针指向的文件中
函数原型:
int fprintf(FILE *stream, const char *format, ...);
参数:
FILE *stream:文件句柄
const char *format:格式控制字符串
返回值:
dprintf()
将字符串写入到文件描述符指向的文件中
函数原型:
int dprintf(int fd, const char *format, ...);
参数:
int fd:文件描述符
const char *format:格式控制字符串
返回值:
sprintf()
函数原型:
int sprintf(char *buf, const char *format, ...);
参数:
char *buf:缓冲区
const char *format:格式控制字符串
返回值:
snprintf()
函数原型:
int snprintf(char *buf, size_t size, const char *format, ...)
参数:
char *buf:缓冲区
size_t size:要写入的字节数
const char *format:格式控制字符串
返回值:
格式化输入:scanf()
函数原型:
int scanf(const char *format, ...);
参数:
const char *format:格式控制字符串
返回值:
fscanf()
函数原型:
int fscanf(FILE *stream, const char *format, ...);
参数:
FILE *stream:文件句柄
const char *format:格式控制字符串
返回值:
sscanf()
函数原型:
int sscanf(const char *str, const char *format, ...);
参数:
const char *str:字符串
const char *format:格式控制字符串
返回值:
文件I/O的内核缓冲
刷新文件I/O的内核缓冲:fsync()
将内核缓冲区的文件数据和文件元数据写入磁盘
函数原型:
int fsync(int fd);
参数:
int fd:文件描述符
返回值:
成功返回0
失败返回-1 设置errno
fdatasync()
仅将内容数据写入磁盘
函数原型:
int fdatasync(int fd);
参数:
int fd:文件描述符
返回值:
成功返回0
失败返回-1 设置errno
sync()
将所有文件I/O内核缓冲区的文件内容数据和元数据更新到磁盘中
函数原型:
void sync();
参数:
返回值:
直接I/O绕过内核缓冲
O_DIRECT标志
需要定义
#define _GNU_SOURCE
三个对其要求:
1、应用程序中用于存放数据的缓冲区,其内存起始地址必须以块大小的整数倍进行对齐
static char buf[4096] _attribute((aligned (4096)))
2、写文件时,文件的位置偏移量必须是块大小的整数倍
lseek(fd, 4096, SEEK_SET);
3、写入到文件的数据大小必须是块大小的整数倍
使用tune2fs命令确定磁盘分区块大小
tune2fs -l /dev/sda1 | grep "Block size"
是哪块磁盘有df命令查看
df -h
stdio缓冲(应用)
标准I/O的stdio缓冲
缓冲类型
无缓冲 _IONBF
行缓冲 _IOLBF
全缓冲 _IOFBF
对stdio缓冲进行设置
setvbuf()
函数原型
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
参数:
FILE *stream:FILE指针
char *buf:如果buf不为NULL,那么buf指向size大小的内存区域将作为该文件的stdio缓冲区,除非选择的时无缓冲
int mode:
无缓冲 _IONBF
行缓冲 _IOLBF
全缓冲 _IOFBF
size_t size:指定缓冲区的大小
返回值:
成功返回0
失败返回非0值 设置errno
当stdio缓冲区的数据被刷入到内核缓冲区或被读取之后,数据就不会存在缓冲区了
setbuf()
建立在setvbuf()之上
函数:
void setbuf(FILE *stream, char *buf);
参数:
FILE *stream:FILE指针
char *buf:buf为NULL无缓冲 ,要么全缓冲
返回值:
setbuffer()
可以指定buf缓冲区的大小
函数原型:
void setbuffer(FILE *stream, char *buf, size_t size);
参数
FILE *stream:文件句柄
char *buf:buf为NULL无缓冲 否则全缓冲
size_t size:缓冲区大小
刷新stdio缓冲
1、关闭文件时会刷新
2、程序退出时会刷新
fflush()
函数原型:
int fflush(FILE *stream);
参数:
FILE *stream:文件句柄,如果为NULL将刷新全部stdio缓冲区
文件描述符与FILE指针互转
fdopen()
函数原型:
FILE *fdopen(int fd, const char *mode);
参数:
int fd:文件描述符
const char *mode:打开文件的模式
返回值:
成功返回FILE指针
失败返回-1
fileno()
函数原型:
int fileno(FILE *stream);
参数:
FILE *stream:FILE指针
返回值:
成功返回文件描述符
失败返回-1
文件属性与目录
1、普通文件 “-”
2、目录文件 “d”
3、字符设备文件 “c”
4、块设备文件 “b”
5、符号链接文件 “l”
6、套接字文件 “s”
7、管道文件 “p”
获取文件属性:stat()
函数原型:
int stat(const char *pathname, struct stat *buf);
参数:
const char *pathname:文件路径
struct stat *buf:存储文件信息的结构体
{
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;
blkcnt_t st_blocks;
struct timespec st_atime; 文件最后被访问的时间
struct timespec st_mtime; 文件最后被修改的时间
struct timespec st_ctime; 文件状态最后被修改的时间
}
st_mode:32位无符号整型 低12位描述文件权限
S_IFMT 0170000 :文件类型字段位掩码
可以判断文件类型的宏:
S_ISREG() 是否为常规文件
S_ISDIR() 是否为目录文件
S_ISCHR() 是否为字符设备文件
S_ISBLK() 是否为块设备文件
S_ISFIFO() 是否为管道文件
S_ISLNK() 是否为链接文件
S_ISSOCK() 是否为套接字文件
struct timespec
{
time_t tv_sec; 秒
syscall_slong_t tv_nsec; 纳秒
}
返回值:
成功返回0
失败返回-1 设置errno
获取文件属性:fstat() lstat()
通过文件描述符获取文件属性
函数原型:
int fstat(int fd, struct stat *buf);
参数:
int fd:文件描述符
struct stat *buf:存储文件信息的结构体
返回值:
成功返回0
失败返回-1 设置errno
lstat()获取链接文件本身的属性
函数原型:
int lstat(const char *pathname, struct stat *buf);
参数:
const char *pathname:文件路径
struct stat *buf:存储文件信息的结构体
返回值:
成功返回0
失败返回-1 设置errno
用户属主
chown()
改变文件的所属用户和所属组
1、只有超级用户进程可以更改
函数原型:
int chown(const char *pathname, uid_t owner, gid_t group);
参数:
const char *pathname, 文件路径
uid_t owner, 文件所有者
gid_t group,文件所属组
返回值:
成功返回0
失败返回-1 设置errno
fchown()
通过文件描述符改变文件的所属者和所属组
函数原型:
int fchown(int fd, uid_t owner, gid_t group);
参数:
int fd, 文件描述符
uid_t owner, 文件所有者
gid_t group,文件所属组
返回值:
lchown()
改变链接文件的所属者和所属组
函数原型:
int lchown(const char *pathname, uid_t owner, gid_t group);
参数:
const char *pathname, 文件路径
uid_t owner, 文件所有者
gid_t group,文件所属组
返回值:
成功返回0
失败返回-1 设置errno
文件访问权限
1、普通权限
S_IRUSR 文件所有者读权限
S_IWUSR 文件所有者写权限
S_IXUSR 文件所有者执行权限
S_IRGRP 同组用户读权限
S_IWGRP 同组用户写权限
S_IXGRP 同组用户执行权限
S_IROTH 其他用户读权限
S_IWOTH 其他用户写权限
S_IXOTH 其他用户执行权限
2、特殊权限
S_ISUID set_user_ID 位权限
S_ISGID set_group_ID位权限
S_ISVTX Sticky 位权限
检查文件权限:access()
函数原型:
int access(const char *pathname, int mode);
参数:
const char *pathname: 文件路径
int mode:文件权限
F_OK:是否存在
R_OK:是否可读
W_OK:是否可写
X_OK:是否可执行
返回值:
成功返回0
失败返回-1
修改文件权限:chmod()
函数原型:
int chmod(const char *pathname, mode_t mode);
参数:
const char *pathname, 文件路径
mode_t mode,用于描述文件权限
返回值:
成功返回0
失败返回-1
fchmod()
函数原型:
int fchmod(int fd, mode_t mode);
参数:
int fd, 文件描述符
mode_t mode, 用于描述文件权限
返回值:
成功返回0
失败返回-1
设置进程权限掩码:umask()
函数原型:
mode_t umask(mode_t mask);
参数:
mode_t mask:需要设置的权限掩码值
返回值:
返回之前的umask值
文件时间属性
修改时间属性:utime()
函数原型:
int utime(const char *pathname, const struct utimbuf *times);
参数:
const char *pathname, 文件路径
const struct utimbuf *times, 将时间属性修改为该参数指定的时间值 (该参数为NULL时,会修改为系统时间)
{
time_t actime; 访问时间
time_t modetime;内容修改时间
}
返回值:
成功返回0
失败返回-1 设置errno
utimes()
时间精度更高
函数原型:
int utimes(const char *pathname, const struct timeval times[2]);
参数:
const char *pathname, 文件路径
const struct timeval times[2], 第一个指定访问时间,第二个指定修改时间
返回值:
成功返回0
失败返回-1 设置errno
futimens()
函数原型:
int futimens(int fd, const struct timespec times[2]);
参数:
int fd, 文件描述符
const struct timespec times[2], 第一个元素指定访问时间,第二个元素指定修改时间
UTIME_NOW 修改为当前时间
UTIME_OMIT 保持不变
返回值:
成功返回0
失败返回-1 设置errno
utimensat()
函数原型:
int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags);
参数:
int dirfd, 目录文件描述符或者ATFDCWD 如果pathname指定绝对路径此参数会被忽略
const char *pathname, 指定文件路径
const struct timespec times[2],
int flags, 可以为0 也可以为AT_SYMLINK_NOFOLLOW 如果为AT_SYMLINK_NOFOLLOW则修改的是符号链接的时间戳
返回值:
成功返回0
失败返回-1 设置errno
创建链接文件
创建硬链接:link()
函数原型:
int link(const char *oldpath, const char *newpath);
参数:
const char *oldpath, 源文件路径
const char *newpath, 新文件的保存路径,如果路径存在则返回错误
返回值:
成功返回0
失败返回-1 设置errno
创建软连接:symlink()
函数原型:
int symlink(const char *target, const char *linkpath);
参数:
const char *target, 源文件 可以是软连接
const char *linkpath, 用于指定软连接文件路径
返回值:
成功返回0
失败返回-1 设置errno
读取软连接文件:readlink()
函数原型:
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
参数:
const char *pathname, 软链接文件路径
char *buf, 用于存放路径信息的缓冲区
size_t bufsiz, 缓冲区大小
返回值:
成功返回0
失败返回-1 设置errno
目录
创建目录:mkdir()
函数原型:
int mkdir(const char *pathname, mode_t mode);
参数:
const char *pathname, 目录路径
mode_t mode, 新建目录的权限设置
返回值:
成功返回0
失败返回-1 设置errno
删除目录:rmdir()
只能删除空目录
函数原型:
int rmdir(const char *pathname);
参数:
const char *pathname:需要删除的目录对应的路径,该目录必须是一个空目录,不能是软连接文件
返回值:
成功返回0
失败返回-1 设置errno
打开目录:opendir()
函数原型:
DIR *opendir(const char *name);
参数:
const char *name:指定需要打开的目录路径,可以是绝对路径也可以是相对路径
返回值:
成功返回指向该目录的句柄
失败返回NULL
读取目录:readdir()
函数原型:
struct dirent *readdir(DIR *dirp);
参数:
DIR *dirp:目录句柄,DIR指针
{
ino_t d_ino; inode编号
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256]; 文件名
}
返回值:
返回一个struct dirent结构体,该结构体表示dirp指向的目录流中的下一个目录条目,在到达目录流末尾或者发生错误时,它返回NULL
重置目录流:rewinddir()
将目录流重置为起点
函数原型:
void rewinddir(DIR *dirp);
参数:
DIR *dirp:目录句柄
返回值:
关闭目录:closedir()
函数原型:
void closedir(DIR *dirp);
参数:
DIR *dirp:目录句柄
返回值:
进程的当前工作目录:getcwd()
函数原型:
char getcwd(char *buf, size_t size);
参数:
char *buf, 将当前工作目录的绝对路径字符串存放在buf中
size_t size, 缓冲区大小
返回值:
成功返回指向buf的指针
失败返回NULL 设置errno
改变当前工作目录:chdir()
函数原型:
int chdir(const char *path);
参数:
const char *path:将当前工作目录修改为指定目录
返回值:
成功返回0
失败返回-1 设置errno
fchdir()
函数原型:
int fchdir(int fd);
参数:
int fd:文件描述符
返回值:
成功返回0
失败返回-1 设置errno
删除文件:unlink()
删除硬链接文件
函数原型:
int unlink(const char *pathname);
参数:
const char *pathname: 要删除的文件路径
返回值:
成功返回0
失败返回-1 设置errno
remove()
可以删除文件或者目录
函数原型:
int remove(const char *pathname);
参数:
const char *pathname: 要删除的文件路径
返回值:
成功返回0
失败返回-1 设置errno
文件重命名:rename()
可以将文件移动到另一个目录下 进操作目录条目不移动实际数据
函数原型:
int rename(const char *oldpath, const char *newpath);
参数:
const char *oldpath, 源文件路径
const char *newpath, 新文件路径
如果newpath指定路径已经存在,则将其覆盖
如果oldpath和newpath指向同一个文件则不发生变化
返回值:
成功返回0
失败返回-1 设置errno
字符串处理
字符串输出:putchar()
输出一个字符 0-127
函数原型:
int putchar(int c);
参数:
int c:需输出的字符
返回值:
出错返回EOF
puts()
自动换行,输出到标准输出设备,将\0转换为\n
函数原型:
int puts(const char *s);
参数:
const char *s:要输出的字符串
返回值:
成功返回非负
失败返回EOF -1
fputc()
函数原型:
int fputc(int c, FILE *stream);
参数:
int c, 要输出的字符
FILE *stream, FILE指针
返回值:
fputs()
函数原型:
int fputs(const char *s, FILE *stream);
参数:
const char *s, 要输出的字符串
FILE *stream, FILE指针
返回值:
成功返回非负
失败返回EOF -1
字符串输入:gets()
读取字符串(包括空格制表换行回车)
函数原型:
chat *gets(char *s);
参数:
char *s:存储输入数据的缓冲区
返回值:
成功返回指向s的指针
失败返回NULL
getchar()
读取一个字符(包括空格制表换行回车)
函数原型:
int getchar(void);
参数:
返回值:
该函数以无符号char强制转换为int的形式返回读取的字符,如果达到文件末尾或者发生错误则返回EOF
fgets()
函数原型:
char *fgets(char *s, int size, FILE *stream);
参数:
char *s, 存储字符串
int size, 要读取的最大字符数
FILE *stream, 文件指针
返回值:
fgetc()
函数原型:
int fgetc(FILE *stream);
参数:
FILE *stream, 文件指针
返回值:
该函数以无符号char强制转换为int的形式返回读取的字符,如果达到文件末尾或者发生错误则返回EOF
字符串拼接:strcat()
函数原型:
char *strcat(char *dest, char *src);
参数:
char *dest, 目标字符串
char *src, 源字符串
返回值:
返回指向目标字符串的dest指针
strncat()
函数原型:
char *strncat(char *dest, char *src, size_t n);
参数:
char *dest, 目标字符串
char *src, 源字符串
size_t n, 要追加的最大字符数
返回值:
返回指向目标字符串的dest指针
字符串拷贝:strcpy()
函数原型:
char *strcpy(char *dest, char *src);
参数:
char *dest, 目标字符串
char *src, 源字符串
返回值:
返回指向目标字符串的dest指针
strncpy()
函数原型:
char *strncpy(char *dest, char *src, size_t n);
参数:
char *dest, 目标字符串
char *src, 源字符串
size_t n, 要拷贝的最大字符数
返回值:
返回指向目标字符串的dest指针
内存填充:memset()
将某一段内存填充
函数原型:
void *memset(void *s, int c, size_t n);
参数:
void *s, 要填充的起始地址
int c, 要填充的值
size_t n, 要填充的字节数
返回值:
bzero
将某一段内存填充为0
函数原型:
void bzero(void *s, size_t n);
参数:
void *s, 要填充的起始地址
size_t n, 要填充的字节数
返回值:
字符串比较:strcmp()
函数原型:
int strcmp(const char *s1, const char *s2);
参数:
s1:进行比较的字符串1
s2:进行比较的字符串2
返回值:
如果返回值小于0,则表示s1<s2
如果返回值大于0,则表示s1>s2
如果返回值等于0,则表示s1=s2
strncmp()
函数原型:
int strncmp(const char *s1, const char *s2, size_t n);
参数:
s1:进行比较的字符串1
s2:进行比较的字符串2
n:最多比较前n个字符
返回值:
如果返回值小于0,则表示s1<s2
如果返回值大于0,则表示s1>s2
如果返回值等于0,则表示s1=s2
字符串查找:strchr()
从前往后找
函数原型:
char *strchr(const char *s, int c);
参数:
s:给定的目标字符串
c:要查找的字符
返回值:
返回c在s中第一次出现的位置,如果未找到则返回NULL
strrchr()
从后往前找
函数原型:
char *strrchr(const char *s, int c);
参数:
s:给定的目标字符串
c:要查找的字符
返回值:
返回c在s中第一次出现的位置,如果未找到则返回NULL
strstr()
查找字符子串
函数原型:
char *strstr(const char *haystack, const char *needle);
参数:
haystack:目标字符串
needle:需要查找的子字符串
返回值:
如果haystack包含needle,则返回needle在haystack中首次出现的位置,如果未找到,则返回NULL
字符串转整形数据:atoi()
十进制
函数原型:
int atoi(const char *nptr);
参数:
返回值:
字符串转整形数据:atol()
函数原型:
long atol(const char *nptr);
参数:
返回值:
字符串转整形数据:atoll()
函数原型:
long long atoll(const char *nptr);
参数:
返回值:
strtol()
指定进制转换
函数原型:
long int strtol(const char *nptr, char **endptr, int base);
参数:
nptr:需要进行转换的目标字符串
endptr:存储第一个无效字符地址
base:数字基数
返回值:
strtoll()
函数原型:
long long int strtol(const char *nptr, char **endptr, int base);
参数:
nptr:需要进行转换的目标字符串
endptr:存储第一个无效字符地址
base:数字基数
返回值:
strtoul()
函数原型:
unsigned long long int strtoul(const char *nptr, char **endptr, int base);
参数:
nptr:需要进行转换的目标字符串
endptr:存储第一个无效字符地址
base:数字基数
返回值:
strtoull()
函数原型:
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
参数:
nptr:需要进行转换的目标字符串
endptr:存储第一个无效字符地址
base:数字基数
返回值:
atof()
函数原型:
double atof(const char *nptr);
参数:
nptr:需要转换的字符串
返回值:
strtof() strtod() strtold()
将字符串转换为float double long double型数据
double strtod(const char *nptr, char **endptr);
float strtod(const char *nptr, char **endptr);
long double strtod(const char *nptr, char **endptr);
系统信息与资源
系统标识:uname()
函数描述:
用于获取当前操作系统内核的名称和信息
函数原型:
int uname(struct utsname *buf);
参数:
buf:struct utsname结构体指针
{
char sysname[]; 当前操作系统名称
char nodename[]; 网络上的名称(主机名)
char release[]; 操作系统内核版本
char version[]; 操作系统发行版本
char machine[]; 硬件架构类型
}
#ifdef GNU_SOURCE
char domainname[]; 当前域名
#endif
返回值:
成功返回0
失败返回-1 设置errno
sysinfo()
函数描述:
系统调用可用于获取一些系统统计信息
函数原型:
int sysinfo(struct sysinfo *info);
参数:
info:struct sysinfo结构体指针
{
long uptime; 自系统启动之后所经过的时间
unsigned long loads[3];
unsigned long totalram; 总的可用内存大小
unsigned long freeram; 未使用的内存大小
unsigned long sharedram;
unsigned long bufferram;
unsigned long totalswap;
unsigned long freeswap;
unsigned long procs 系统当前进程数量
unsigned long totalhigh;
unsigned long freehigh;
unsigned long mem_unit; 内存单元大小
char _f[20-2*sizeof(long)-sizeof(int)];
}
返回值:
成功返回0
失败返回-1 设置errno
gethostname()
函数描述:
用于单独获取Linux系统主机名
函数原型:
int gethostname(char *name, size_t len);
参数:
name:用于存放主机名的字符串缓冲区
len:缓冲区长度
返回值:
成功返回0
失败返回-1 设置errno
sysconf()
函数描述:
库函数,可以在运行时获取系统的一些配置信息
函数原型:
long sysconf(int name);
参数:
name:_SC_ARG_MAX:exec族函数的参数的最大长度
_SC_CHILD_MAX:每个用户最大并发进程数
_SC_HOST_NAME_MAX:主机名最大长度
_SC_LOGIN_NAME_MAX:登录名最大长度
_SC_CLK_TCK:系统节拍率 每秒时钟滴答数
_SC_PAGESIZE:系统页大小
。。。
返回值:
时间与日期
获取时间:time()
函数描述:
用于获取当前时间
函数原型:
time_t time(time_t *tloc);
参数:
tloc:如果tloc参数不是NULL,则返回值也存储在tloc指向的内存中
返回值:
成功返回自1970-01-01以来的时间值
失败返回-1
gettimeofday()
函数描述:
函数原型:
int gettimeofday(struct timeval *tv, struct timezone *tz);
参数:
tv:结构体变量指针
tz:NULL
返回值:
成功返回0
失败返回-1 设置errno
时间转换:ctime()
函数描述:
可以将日历时间转换为可打印输出的字符串形式
函数原型:
char *ctime(const time_t timep);
可重入:char *ctime_r(const time_t timep, char *buf);
参数:
timep:时间变量指针
buf:缓冲区
返回值:
成功返回转换后的字符串指针
失败返回NULL
localtime()
函数描述:
该函数可以把time()或者gettimeofday()得到的秒数变成一个struct tm结构体所表示的时间,该时间对应的是本地时间
函数原型:
struct tm *localtime(const time_t timep);
struct tm *localtime_r(const time_t timep, struct tm *result);
参数:
timep:time_t时间变量对应的指针
result:struct tm类型的结构体指针
{
}
返回值:
成功返回result
失败返回NULL
gmtime()
函数描述:
得到UTC国际标准时间
函数原型:
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_r *timep, struct tm *result);
参数:
timep:time_t时间变量对应的指针
result:struct tm类型的结构体指针
返回值:
成功返回result
失败返回NULL
mktime()
函数描述:
可以将使用struct tm分解的时间转化为time_t时间,c库函数
函数原型:
time_t mktime(struct tm *tm);
参数:
tm:需要进行转换的分解时间
返回值:
成功返回日历时间
asctime()
函数描述:
可以将时间转换为可打印输出的字符串形式
函数原型:
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
参数:
tm:需要进行转化的struct tm表示的时间
buf:用于存放转换得到的字符串
返回值:
失败返回NULL
成功返回char *类型指针
strftime()
函数描述:
可以将struct tm变量表示的分解时间转换为格式化字符串
函数原型:
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
参数:
s:指向一个缓存区的指针,用于存放生成的字符串
max:字符串的最大字节数
format:控制显示格式
tm:struct tm类型结构体指针
返回值:
进程时间
程序创建后,使用cpu资源的时间总数
1、用户cpu时间(用户态)
2、系统cpu时间(内核态)
获取进程时间:times()
函数描述:
用于获取当前进程时间
函数原型:
clock_t times(struct tms *buf);
参数:
buf:保存当前进程时间信息
返回值:
成功返回系统节拍数
失败返回-1
clock()
函数描述:
进程使用的总的cpu时间
函数原型:
clock_t clock(void);
参数:
返回值:
到目前为止的进程的时间
失败返回-1
生成随机数:rand()
函数描述:
用于获取随机数
函数原型:
int rand(void);
参数:
返回一个介于0到RAND_MAX之间的值
返回值:
srand()
函数描述:
设置一个随机数种子
函数原型:
void srand(unsigned int seed);
参数:
seed:指定一个随机数中,int类型的数据
返回值:
常用 srand(time(NULL));
休眠sleep() usleep() nanosleep()
函数描述:
函数原型:
unsigned int sleep(int sec);
int usleep(useconds_t usec);
int nanosleep(const struct timespec *req, struct timespec *rem);
参数:
sec:秒
usec:微秒
req:用于设置休眠时间长度
rem:NULL
返回值:
休眠时间到达后返回0
失败返回-1
使用堆内存
分配与释放 malloc() free()
函数描述:
在堆上申请内存与释放
函数原型:
void *malloc(size_t size);
参数:
size:字节为单位
返回值:
返回指向该段内存的地址
失败返回NULL
calloc()
函数描述:
动态分配内存地址并初始化为0
函数原型:
void *calloc(size_t nmemb, size_t size);
参数:
分配nmemb个长度为size的连续空间并且初始化为0
返回值:
返回指向该段内存的地址
失败返回NULL
分配对其内存
posix_memalign()
函数描述:
申请字节对齐的内存空间
函数原型:
int posix_memalign(void **memptr, size_t alignment, size_t size);
参数:
memptr:申请成功会将内存地址存放在*memptr
alignment:内存对其的字节数 2的幂次方
size:设置分配的内存大小(字节)
返回值:
成功返回0
失败返回非0
aligned_alloc()
函数描述:
申请字节对齐的内存空间
函数原型:
void *aligned_alloc(size_t alignment, size_t size);
参数:
alignment:内存对其的字节数 2的幂次方
size:设置分配的内存大小(字节)必须是alignment的整数倍
返回值:
成功返回内存空间的指针,起始地址是alignment的整数倍
失败返回NULL
信号
基本概念
信号是发生事件是对进程的一种通知
中断信号:SIGINT
退出信号:SIGQUIT
非法信号:SIGILL
终止信号:SIGABRT
总线信号:SIGBUS
算术错误信号:SIGFPE
必杀信号:SIGKILL
自定义信号:SIGUSR1, SIGUSR2
内存引用无效:SIGSEGV
管道 socket:SIGPIPE
定时器时间到:SIGALRM
SIGTERM:终止进程
SIGCHLD:子进程终止,子进程收到信号停止或者恢复时
SIGCONT:进程处于停止的进程恢复运行
SIGSTOP:用于停止进程(必停)
SIGTSTP:发送给前台进程组中的每一个进程,使其停止运行
SIGXCPU:进程cpu时间超出限制
SIGPOLL/SIGIO:用于提示一个异步IO事件
SIGSYS:进程发起的系统调用有误
进程对信号的处理
signal()
函数描述:
函数原型:
typedef void (*sig_t)(int);
sig_t signal(int signum, sig_t handler);
参数:
signum:指定需要设置的信号
handler:指定用户自定义信号处理函数,也可以设置为SIG_IGN或者SIG_DFL,SIG_IGN表示忽略该信号,SIG_DFL表示执行系统默认操作,sig_t函数指针的int型指的是当初发该函数的信号可将多个信号绑定到同一个信号处理函数,此时可以通过此参数判断当前触发的是哪个信号
#define SIG_ERR ((sig_t) -1)
#define SIG_DFL ((sig_t) 0)
#define SIG_IGN ((sig_t) 1)
返回值:
sigaction()
函数描述:
允许单独获取信号的处理函数而不是设置,并且可以设置各种属性对调用信号处理函数时的行为施以更加精准的控制
函数原型:
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
参数:
signum:需要设置的信号
act:描述了信号的处理方式 可以为NULL
oldact:将之前的处理方式等信息返回 可以为NULL
struct sigcation{
void (*sa_handler)(int)
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags
}
返回值:
成功返回0
失败返回-1 设置errno
向进程发送信号
kill()
函数描述:
系统调用,将信号发送给指定的进程或进程组中的每一个进程
函数原型:
int kill(pid_t pid, int sig)
参数:
pid:进程pid,
sig:要发送的信号
返回值:
成功返回0
失败返回-1 设置errno
raise()
函数描述:
进程向自身发送信号
函数原型:
int raise(int sig);
参数:
sig:需要发送的信号
返回值:
成功返回0,失败返回非0
alaram()
函数描述:
可以设置一个定时器,当定时器时间到内核会向进程发送SIGALRM
函数原型:
unsigned int alarm(unsigned int seconds);
参数:
seconds;设置定时时间,以秒为单位,如果等于0则表示取消之前的alarm闹钟
返回值:
如果在调用之前,alarm闹钟还没超时,则该闹钟的剩余时间作为本次返回值,之前设置的闹钟被新的替代,否则返回0
pause()
函数描述:
系统调用可以使进程暂停进入休眠状态,直到进程捕获到一个信号为止
函数原型:
int pause(void);
参数:
返回值:
执行了信号处理函数并返回时 返回-1
信号集sigset_t
初始化信号集sigemptyset()
函数描述:
初始化信号集,使其不包含任何信号
函数原型:
int sigemptyset(sigset_t *set);
参数:
set:指向要进行初始化的信号集
返回值:
sigfillset()
函数描述:
初始化信号集使其包含所有信号
函数原型:
int sigfillset(sigset_t *set);
参数:
set:指向要进行初始化的信号集
返回值:
向信号集中添加信号sigaddset()
函数描述:
函数原型:
int sigaddset(sigset* set, int signum);
参数:
set:指向要进行初始化的信号集
signum:需要添加的信号
返回值:
向信号集中删除信号sigdelset()
函数描述:
函数原型:
int sigdelset(sigset* set, int signum);
参数:
set:指向要进行初始化的信号集
signum:需要删除的信号
返回值:
测试信号sigismember()
函数描述:
测试某一个信号是否指定的信号集中
函数原型:
int sigsimember(const sigset_t *set, int signum);
参数:
set:指向要进行初始化的信号集
signum:需要测试的信号
返回值:
如果信号在信号集中返回1
如果信号不在信号集中返回0
失败返回-1 设置errno
信号掩码
用于阻塞信号
sigprocmask()
函数描述:
可以显示添加或移除信号
函数原型:
int sigprocmask(int how, const sigset* set, sigset_t *oldset);
参数:
how:指定调用函数的一些行为
SIG_BLOCK:将参数set所指向的信号集内的所有信号添加到进程的信号掩码之中
SIG_UNBLOCK:将set指向的信号集内的所有信号从进程掩码中移除
SIG_SETMASK:进程信号掩码直接设置为set信号集
set:将参数set指向的信号集内的所有信号添加到信号掩码中
oldset:如果不为NULL,在信号掩码中添加新的信号之前,获取到进程当前的信号掩码,存放在oldset指定的信号集中
返回值:
成功返回0
失败返回-1 设置errno
实时信号
sigpending()
函数描述:
获取进程中处于等待状态的信号
函数原型:
int sigpending(sigset_t *set);
参数:
set:
返回值:
成功返回0
失败返回-1 设置errno
sigqueue()
函数描述:
发送实时信号及伴随数据
函数原型:
int sigqueue(pid_t pid, int sig, const union sigval value);
参数:
pid:指定接收信号的进程对应的pid,将信号发送给该进程
sig:指定需要发送的信号,设置为0检查参数pid所指定的进程是否存在
value:指定信号的伴随数据,union sigval数据类型
返回值:
成功返回0
失败返回-1 设置errno
异常终止:abort()
1、解除对SIGABRT信号的阻塞
2、向本进程发送SIGABRT信号,导致进程异常终止
函数描述:
函数原型:
void abort(void)
参数:
返回值:
进程
什么是进程?
进程是一个应用程序的执行实例,也就是系统中正在运行的程序
什么是进程号?
Linux下的每一个进程都有一个进程号,进程号是一个整数,是进程的唯一标识
终止进程
exit()
函数描述:
库函数
函数原型:
void exit(int status);
参数:
status:表示进程终止时的状态,0正常终止,非0表示非正常终止
返回值:
_exit()
函数描述:
系统调用
函数原型:
void _exit(int status);
参数:
status:表示进程终止时的状态,0正常终止,非0表示非正常终止
返回值:
注册终止处理函数atexit()
函数描述:
函数原型:
void atexit(void (*function)(void));
参数:
function:函数指针
返回值:
进程的环境变量
1、使用env查看环境变量
2、echo打印某一个环境变量
3、export修改某一个环境变量
4、unset删除环境变量
常见的环境变量
1、PATH:用于指定可执行程序的搜索路径
2、HOME:用于指定当前用户的家目录
3、LOGNAME:用于指定当前登陆的用户
4、HOSTNAME:用于指定主机名
5、SHELL:用于指定当前的shell解析器
6、PWD:用于指定进程的当前工作目录
这些环境变量都以字符串形式存储在字符串数组中,叫做环境表
表中每一个字符串都是按照“name=value”形式定义,字符数组以NULL结尾
每个应用程序都有一组环境变量,进程在创建的时候,他的环境变量从其父进程继承
有三种方式获取环境变量
1、通过environ变量获取
这个变量是一个全局变量,可以在程序中直接使用,extern char **environ
2、通过main函数参数获取
int main(int argc, char argv[], char *env[]);
3、通过getenv获取
函数描述:
获取指定的环境变量
函数原型:
char *getenv(const char *name);
参数:
name:环境变量名
返回值:
如果存在则返回对应的字符串
不存在则返回NULL
添加环境变量:putenv()
函数描述:
可以向进程的环境变量中添加一个新的环境变量,或者修改一个已经存在的环境变量
函数原型:
int putenv(char *string);
参数:
string:字符串指针,指向name=value的字符串
返回值:
成功返回0
失败返回非0 设置errno
添加环境变量:setenv()
函数描述:
可以向进程的环境变量中添加一个新的环境变量,或者修改一个已经存在的环境变量
函数原型:
int setenv(const char *name, const char *value, int overwrite);
参数:
name:需要添加或修改环境变量名称
value:环境变量的值
overwrite:若name标识的环境变量已经存在,在参数overwrite为0的情况下,setenv()函数将不改变现有的环境变量的值,如果参数overwrite为非0,若name标识的环境变量已存在,则覆盖,不存在则添加新的环境变量
返回值:
成功返回0
失败返回非0 设置errno
删除环境变量:unsetenv()
函数描述:
函数原型:
int setenv(const char *name);
参数:
返回值:
清空环境变量:clearenv()
函数描述:
清空环境变量,把environ设置为NULL
函数原型:
int clearenv(void);
参数:
返回值:
函数描述:
函数原型:
参数:
返回值:
创建子进程
所有进程都是由父进程创建出来的
fork()
函数描述:
创建子进程
函数原型:
pid_t fork(void);
参数:
返回值:
fork会返回两次,子进程返回一次,父进程返回一次。
>0 返回的是子进程的pid
=0 返回的是子进程的返回值
父子进程间的文件共享
子进程会拷贝父进程所有的文件描述符,子进程相当于父进程的副本
父子进程间的竞争关系
fork之后父进程,子进程谁先运行?
无法确定哪个先运行
监视子进程
子进程状态改变:
SIGCHLD信号的三种触发情况
1、子进程终止
2、子进程收到停止信号而停止SIGSTOP SIGTSTP
3、子进程在停滞状态下,收到恢复信号而恢复运行
wait()
函数描述:
系统调用,等待进程的任一子进程终止,同时获取子进程的终止状态信息,回收子进程的一些资源
函数原型:
pid_t wait(int *status);
参数:
status:用于存放子进程终止时的状态信息,可以为NULL,表示不接收子进程终止时的状态信息
返回值:
成功返回终止子进程的对应进程号
失败返回-1
可以通过宏来检查status:
WIFEXITED(status);正常返回true
WEXITSTATUS(status);返回子进程退出状态,是一个数值,其实就是子进程调用_exit()或exit()时指定的退出状态
WIFSIGNALED(status);进程被信号终止,则返回true
WTERMSIG(status);返回导致子进程终止的信号编号
WCOREDUMP(status);子进程终止时产生了核心转储文件,则返回true
wait函数只能按顺序回收终止的子进程,谁先终止回收谁,如果子进程没有终止则进入阻塞状态,wait无法发现暂停运行的子进程
waitpid()
函数描述:
更加灵活
函数原型:
pid_t waitpid(pid_t pid, int *status, int options);
参数:
pid:需要等待的子进程
pid>0 表示等待进程号为pid的子进程
pid=0 等待与调用进程同一个进程组的所有子进程
pid=-1 等待任意子进程
pid<-1 等待进程组标识符与pid绝对值相等的所有子进程
status:用于存放子进程终止时的状态信息,可以为NULL,表示不接收子进程终止时的状态信息
options:标志位掩码
WNOHANG:如果子进程没有发生状态改变,立即返回
WUNTRACED:除了返回终止的子进程的状态信息外,还返回因信号而停止(暂停运行)的子进程状态信息
WCONTINUED:返回因收到SIGCONT信号而恢复运行的子进程的状态
返回值:
僵尸进程与孤儿进程
孤儿进程
父进程先结束,此时子进程成为一个孤儿,我们把这种子进程称为孤儿进程,所有孤儿进程都会成为祖先进程(1)的子进程
僵尸进程
子进程终止,父进程没有收尸(没有使用wait、waitpid函数回收),子进程暴尸荒野,成为僵尸进程
执行新程序
execve()
函数描述:
系统调用,可以将一个新的程序加载到进程空间,使用新程序替换旧程序,运行新程序的main函数
函数原型:
int execve(const char *filename, char *const argv[], char *const envp[]);
参数:
filename:需要载入的新程序的路径
argv:
envp:环境变量数组
返回值:
函数一旦返回就表示发生了错误
exec族库函数
execl()\execlp()\execle()
函数描述:
函数原型:
int execl(const char *path, const char *arg, .../* (char*)NULL */);
int execlp(const char *file, const char *arg, .../* (char*)NULL */);
int execle(const char *path, const char *arg, .../* (char*)NULL, char* const envp[] */);
参数:
path:新程序的路径
file:提供新程序文件名,它会去path环境变量所定义的这些路径中寻找新程序
arg:可变参函数,参数依次排列
envp:环境变量表
返回值:
execv()\execvp()\execvpe()
函数描述:
函数原型:
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
参数:
path:新程序的路径
file:提供新程序文件名,它会去path环境变量所定义的这些路径中寻找新程序
argv:数组以NULL结尾
envp:环境变量表
返回值:
system库函数
函数描述:
可以很方便的执行shell命令
函数原型:
int system(const char *command);
参数:
command:需要执行的shell命令
返回值:
commond为NULL,如果当前系统存在shell解析器返回非0
如果创建子进程失败返回-1
如果加载shell解析器失败会调用_exit返回127
无法获取子进程的状态信息,返回-1
如果成功则会返回shell子进程的终止状态信息
vfork系统调用
fork函数的缺点
1、在绝大多数情况下,创建的子进程中会调用exec去加载一个新的程序
2、fork创建子进程后,子进程会拷贝父进程的代码段数据段堆栈等,当子进程使用exec加载一个新的程序时,新的程序又会替换掉原有的代码段数据段堆栈等,导致效率变低
fork与vfork的区别
1、vfork,子进程在终止或成功调用exec函数之前,子进程与父进程共享地址空间,共享所有内存
2、vfork会保证子进程先运行,父进程此时处于阻塞挂起状态,在子进程终止或者成功调用exec函数之后,父进程才会运行
进程状态与进程的关系
进程状态:
1、运行状态或可执行状态
2、可中断睡眠状态
3、不可中断睡眠状态
4、停止状态
5、僵尸状态
6、死亡状态
进程间的关系
1、无关系
2、父子关系
3、进程组
函数描述:
通过getpgrp()\getpgid()获取进程的进程组ID
通过setpgid()\setpgrp()可以修改进程所属进程组
函数原型:
pid_t getpgid(pid_t pid);
pid_t getpgrp(void);
int setpgid(pid_t pid, pid_t pgid);
int setpgrp(void);
参数:
pid:要获取进程组id的进程
pgid:要修改的进程组id
返回值:
成功返回进程组id
会话
1、每个进程组必定属于一个会话
2、一个会话包含一个或多个进程组,最多只能有一个前台进程组
3、每个会话都有一个会话首领,即创建会话的进程
4、每个会话都有ID标识,称为会话ID,可以用getsid函数获取进程sid,可以使用setsid创建一个会话
fork后,父进程信号处理机制对子进程的影响
父进程信号处理函数对子进程的影响
fork后子进程会继承父进程绑定的信号处理函数,加载新的程序后,就不会在继承这个信号处理函数了
父进程信号掩码对子进程的影响
fork后子进程会继承父进程的信号掩码,加载新程序后,还是会继承这个信号掩码
守护进程
1、创建子进程,终止父进程
2、子进程调用setsid创建新的会话
3、将工作目录更改为"/"根目录
4、重新设置文件权限掩码umask
5、关闭打开的文件描述符
6、忽略SIGCHLD信号
进程间的通信
1、数据传输
2、资源共享
3、通知时间
4、进程控制
由os参与,提供一份所有进程都可以访问的公共资源
公共资源包括:内存块、队列、文件
进程间通信的手段有哪些
同一台主机:
1、管道
有名管道:用于父子进程或具有血缘关系的进程 int pipe(int pipefd[2]);
无名管道:同一台主机上任意进程进行通信
2、信号
3、共享内存
4、消息队列
5、信号量
不同主机:
1、socket