相关代码资源:xLinux: linux,网络编程阶段代码
1、IO
库函数
错误处理:
1. errno
errno
是一个全局变量(在大多数实现中),用于报告系统调用的错误。当系统调用(如文件操作、内存分配等)失败时,errno
会被设置为一个特定的错误码,以指示发生了什么类型的错误。errno
的定义位于<errno.h>
(或<stdlib.h>
在某些系统上)头文件中。
注意:由于errno
是全局的,它可能会被多个线程同时访问,因此在多线程程序中需要特别注意其线程安全性。许多现代系统提供了线程局部存储(TLS)版本的errno
,以避免这种问题。
使用示例:
#include <stdio.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
int main() { | |
FILE *fp = fopen("nonexistentfile.txt", "r"); | |
if (fp == NULL) { | |
printf("Error opening file: %s\n", strerror(errno)); | |
} | |
return 0; | |
} |
2. perror
perror
函数用于打印一条描述最近发生的错误的消息到标准错误(stderr)。它会自动使用errno
的值来确定要打印的错误消息。perror
的原型定义在<stdio.h>
头文件中。
使用示例:
#include <stdio.h> | |
#include <stdlib.h> | |
int main() { | |
FILE *fp = fopen("nonexistentfile.txt", "r"); | |
if (fp == NULL) { | |
perror("Error opening file"); | |
} | |
return 0; | |
} |
在这个例子中,如果文件打开失败,perror
会打印类似于“Error opening file: No such file or directory”的消息(具体消息取决于errno
的值和系统的本地化设置)。
3. strerror
strerror
函数用于将errno
的值转换为对应的错误消息字符串。它接受一个errno
值作为参数(尽管在实际使用中,你通常会传递errno
宏本身,因为它指向当前的错误码),并返回一个指向错误消息字符串的指针。这个字符串是静态分配的,因此每次调用strerror
时,之前的返回值可能会被覆盖。strerror
的原型定义在<string.h>
头文件中。
使用示例(已在前面的errno
示例中展示):
printf("Error opening file: %s\n", strerror(errno)); |
文件
输入
1. fgetc
- 函数原型:
int fgetc(FILE *stream);
- 头文件:
#include <stdio.h>
- 返回值: 成功时返回读取的字符(作为无符号字符转换为int),遇到文件结束符(EOF)或错误时返回EOF。
- 功能: 从指定的文件流
stream
中读取下一个字符。
2. fgets
- 函数原型:
char *fgets(char *str, int n, FILE *stream);
- 头文件:
#include <stdio.h>
- 返回值: 成功时返回指向
str
的指针,遇到文件结束符(EOF)或读取错误时返回NULL。 - 功能: 从指定的文件流
stream
中读取最多n-1
个字符(为了留出空间给字符串结束符\0
),直到遇到换行符、文件结束符或读取了n-1
个字符为止。
3. fread
- 函数原型:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- 头文件:
#include <stdio.h>
- 返回值: 成功读取的元素个数,可能小于请求的数量(
nmemb
)。 - 功能: 从指定的文件流
stream
中读取数据到ptr
指向的数组中。每次读取size
字节,共读取nmemb
次。
4. fscanf
- 函数原型:
int fscanf(FILE *stream, const char *format, ...);
- 头文件:
#include <stdio.h>
- 返回值: 成功匹配并赋值的输入项数,遇到文件结束符或读取错误时可能小于预期。
- 功能: 根据指定的格式字符串
format
从文件流stream
中读取数据,并将读取的数据存储到后续参数指定的变量中。
5. getc
- 函数原型:
int getc(FILE *stream);
- 头文件:
#include <stdio.h>
- 返回值: 成功时返回读取的字符(作为无符号字符转换为int),遇到文件结束符(EOF)或错误时返回EOF。
- 功能: 类似于
fgetc
,从指定的文件流stream
中读取下一个字符。
6. gets
(已废弃)
- 函数原型:
char *gets(char *str);
- 头文件:
#include <stdio.h>
(但不建议使用,因为它不安全) - 返回值: 成功时返回指向
str
的指针,遇到文件结束符(EOF)或读取错误时返回NULL。 - 功能: 从标准输入读取一行文本,直到遇到换行符或EOF,但不包括换行符。由于可能导致缓冲区溢出,该函数已被废弃。
7. scanf
- 函数原型:
int scanf(const char *format, ...);
- 头文件:
#include <stdio.h>
- 返回值: 成功匹配并赋值的输入项数,遇到文件结束符或读取错误时可能小于预期。
- 功能: 根据指定的格式字符串
format
从标准输入读取数据,并将读取的数据存储到后续参数指定的变量中。
8. getchar
- 函数原型:
int getchar(void);
- 头文件:
#include <stdio.h>
- 返回值: 成功时返回读取的字符(作为无符号字符转换为int),遇到文件结束符(EOF)或错误时返回EOF。
- 功能: 从标准输入读取下一个字符。
输出
1. fputc
- 函数原型:
int fputc(int char, FILE *stream);
- 返回值: 成功时返回写入的字符(转换为
unsigned char
后再转换为int
),失败时返回EOF
。 - 头文件:
#include <stdio.h>
- 功能: 将一个字符(实际上是以
int
形式传递的)写入到指定的文件流stream
中。
2. fputs
- 函数原型:
int fputs(const char *s, FILE *stream);
- 返回值: 成功时返回非负值,失败时返回
EOF
。 - 头文件:
#include <stdio.h>
- 功能: 将字符串
s
(不包括结尾的空字符\0
)写入到指定的文件流stream
中。
3. fwrite
- 函数原型:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
- 返回值: 成功写入的元素个数。
- 头文件:
#include <stdio.h>
- 功能: 将
ptr
指向的数组中的数据写入到指定的文件流stream
中。每次写入size
字节,共写入nmemb
次。
4. fprintf
- 函数原型:
int fprintf(FILE *stream, const char *format, ...);
- 返回值: 成功写入的字符数(不包括结尾的空字符),出错时返回负值。
- 头文件:
#include <stdio.h>
- 功能: 根据指定的格式字符串
format
向文件流stream
写入数据。
5. putc
- 函数原型:
int putc(int char, FILE *stream);
- 返回值: 成功时返回写入的字符(转换为
unsigned char
后再转换为int
),失败时返回EOF
。 - 头文件:
#include <stdio.h>
- 功能: 类似于
fputc
,将一个字符(以int
形式传递)写入到指定的文件流stream
中。
6. puts
- 函数原型:
int puts(const char *s);
- 返回值: 成功时返回非负值,失败时返回
EOF
。 - 头文件:
#include <stdio.h>
- 功能: 将字符串
s
(包括结尾的空字符\0
,但puts
会在输出后自动添加一个换行符\n
)写入到标准输出。
7. printf
- 函数原型:
int printf(const char *format, ...);
- 返回值: 成功写入的字符数(不包括结尾的空字符),出错时返回负值。
- 头文件:
#include <stdio.h>
- 功能: 根据指定的格式字符串
format
向标准输出写入数据。
8. putchar
- 函数原型:
int putchar(int char);
- 返回值: 成功时返回写入的字符(转换为
unsigned char
后再转换为int
),失败时返回EOF
。 - 头文件:
#include <stdio.h>
- 功能: 将一个字符(以
int
形式传递)写入到标准输出。
打开:
fopen
- 函数原型:
FILE *fopen(const char *filename, const char *mode);
- 头文件:
#include <stdio.h>
- 功能:根据指定的文件名(
filename
)和模式(mode
)打开一个文件,并返回一个指向FILE
的指针,该指针用于后续的文件操作。如果打开文件失败,则返回NULL
。 - 模式(
mode
):"r"
:以只读方式打开文件。该文件必须存在。"w"
:以只写方式打开文件。如果文件存在,则长度被截断为零,即该文件内容会消失。如果文件不存在,则创建新文件。"a"
:以追加方式打开文件。如果文件存在,写入的数据会被追加到文件尾。如果文件不存在,则创建新文件。"r+"
:以读/写方式打开文件。该文件必须存在。"w+"
:以读/写方式打开文件。如果文件存在,则文件长度被截断为零,即该文件内容会消失。如果文件不存在,则创建新文件。"a+"
:以读/写方式打开文件,数据将被追加到文件尾。如果文件不存在,则创建新文件。
关闭
fclose
- 函数原型:
int fclose(FILE *stream);
- 头文件:
#include <stdio.h>
- 功能:关闭一个由
fopen
、freopen
或fdopen
函数打开的文件流(stream
)。如果成功,返回0
;如果失败,返回EOF
。 - 注意:使用完文件后,应及时关闭它,以释放相关资源。
fclose
会刷新缓冲区中的输出数据(如果有的话),关闭文件,并释放与stream
相关联的所有资源。
定位:
fseek
- 函数原型:
int fseek(FILE *stream, long offset, int whence);
- 功能:
fseek
函数用于重新定位文件流(stream
)中的位置指针。它根据whence
参数指定的起点和offset
参数指定的偏移量来移动位置指针。 - 参数:
FILE *stream
:指向FILE
对象的指针,该对象标识了要操作的文件流。long offset
:从whence
指定的位置开始计算的偏移量(以字节为单位)。int whence
:起始位置,它是一个宏定义,可以是以下值之一:SEEK_SET
:文件的开头。SEEK_CUR
:当前位置。SEEK_END
:文件的末尾。
- 返回值:成功时返回
0
,失败时返回非零值。
ftell
- 函数原型:
long ftell(FILE *stream);
- 功能:
ftell
函数用于获取当前文件流(stream
)中的位置指针的位置(即当前读写位置)。 - 参数:
FILE *stream
:指向FILE
对象的指针,该对象标识了要查询的文件流。
- 返回值:成功时返回当前位置(以字节为单位),失败时返回
-1L
。
目录
打开目录
- 函数:
DIR *opendir(const char *name);
- 头文件:
<dirent.h>
- 功能:打开指定的目录
name
,并返回一个指向DIR
的指针,该指针用于后续的目录读取操作。如果打开失败,返回NULL
。
切换目录
- 函数:
int chdir(const char *path);
- 头文件:
<unistd.h>
- 功能:将当前工作目录更改为
path
指定的目录。成功时返回0
,失败时返回-1
。
读取目录
- 函数:
struct dirent *readdir(DIR *dirp);
- 头文件:
<dirent.h>
- 功能:读取
dirp
指向的目录流中的下一个目录项。如果到达目录末尾或发生错误,则返回NULL
。
创建目录
- 函数:
int mkdir(const char *pathname, mode_t mode);
- 头文件:
<sys/stat.h>
和<sys/types.h>
(可能需要) - 功能:创建名为
pathname
的新目录,其权限位由mode
指定。成功时返回0
,失败时返回-1
。
删除目录
- 函数:
int rmdir(const char *pathname);
- 头文件:
<unistd.h>
- 功能:删除名为
pathname
的空目录。成功时返回0
,失败时返回-1
。
获取绝对路径
- 函数:
char *getcwd(char *buf, size_t size);
- 头文件:
<unistd.h>
- 功能:将当前工作目录的绝对路径复制到
buf
指向的数组中。如果buf
为NULL
,则函数分配足够的内存来存储路径(这种情况需要手动释放内存)。成功时返回指向buf
的指针,失败时返回NULL
。
定位(在目录流中)
-
函数:
long int telldir(DIR *dirp);
-
头文件:
<dirent.h>
-
功能:返回目录流
dirp
的当前位置(一个相对于目录开头的偏移量)。这可以用于在读取目录时记录位置。 -
函数:
void seekdir(DIR *dirp, long int loc);
-
头文件:
<dirent.h>
-
功能:将目录流
dirp
的位置设置为loc
,该位置是之前通过telldir
函数获得的。 -
函数:
void rewinddir(DIR *dirp);
-
头文件:
<dirent.h>
-
功能:将目录流
dirp
的位置重置为流的开头。
关闭目录
- 函数:
int closedir(DIR *dirp);
- 头文件:
<dirent.h>
- 功能:关闭由
opendir
函数打开的目录流dirp
。成功时返回0
,失败时返回-1
。
系统调用
文件操作
open
- 原型:
int open(const char *pathname, int flags, ...);
- 头文件:
<fcntl.h>
或<sys/types.h>
,<sys/stat.h>
,<unistd.h>
- 返回值:成功时返回非负整数(文件描述符),失败时返回-1并设置errno。
- 功能:打开或创建一个文件,并返回一个文件描述符用于后续的读写操作。
read
- 原型:
ssize_t read(int fd, void *buf, size_t count);
- 头文件:
<unistd.h>
- 返回值:成功时返回读取的字节数,当到达文件末尾时返回0,失败时返回-1并设置errno。
- 功能:从文件描述符指向的文件中读取数据到缓冲区。
write
- 原型:
ssize_t write(int fd, const void *buf, size_t count);
- 头文件:
<unistd.h>
- 返回值:成功时返回写入的字节数,失败时返回-1并设置errno。
- 功能:向文件描述符指向的文件中写入数据。
close
- 原型:
int close(int fd);
- 头文件:
<unistd.h>
- 返回值:成功时返回0,失败时返回-1并设置errno。
- 功能:关闭一个打开的文件描述符。
lseek
- 原型:
off_t lseek(int fd, off_t offset, int whence);
- 头文件:
<unistd.h>
- 返回值:成功时返回新的文件偏移量(相对于文件开头),失败时返回(off_t)-1并设置errno。
- 功能:移动文件描述符的读写位置。
文件属性
stat
- 原型:
int stat(const char *pathname, struct stat *buf);
- 头文件:
<sys/stat.h>
- 返回值:成功时返回0,失败时返回-1并设置errno。
- 功能:获取文件的状态信息。
lstat
- 原型:
int lstat(const char *pathname, struct stat *buf);
- 头文件:
<sys/stat.h>
- 返回值:成功时返回0,失败时返回-1并设置errno。
- 功能:类似于
stat
,但当参数为符号链接时,返回链接本身的信息。
用户和组信息
getpwuid
- 原型:
struct passwd *getpwuid(uid_t uid);
- 头文件:
<sys/types.h>
,<pwd.h>
,<unistd.h>
- 返回值:成功时返回指向
passwd
结构的指针,失败时返回NULL。 - 功能:通过用户ID获取用户信息。
getgrgid
- 原型:
struct group *getgrgid(gid_t gid);
- 头文件:
<sys/types.h>
,<grp.h>
,<unistd.h>
- 返回值:成功时返回指向
group
结构的指针,失败时返回NULL。 - 功能:通过组ID获取组信息。
文件锁
fcntl
- 原型:
int fcntl(int fd, int cmd, ... /* arg */ );
- 头文件:
<fcntl.h>
- 返回值:取决于
cmd
参数,通常成功时返回非负值,失败时返回-1并设置errno。 - 功能:文件控制操作,包括设置/获取文件锁等。
cmd参数(与文件锁相关):
F_GETLK
:获取文件锁的信息。F_SETLK
:设置文件锁,但不会阻塞。F_SETLKW
:设置文件锁,如果发生冲突则阻塞。
lockf
- 原型:
int lockf(int fd, int cmd, off_t len);
- 头文件:
<unistd.h>
- 返回值:成功时返回0,失败时返回-1并设置errno。
- 功能:对文件的一部分进行加锁或解锁操作。
时间处理:
1. time()
函数原型:time_t time(time_t *tloc);
头文件:<time.h>
功能:获取当前时间(自1970年1月1日(称为Unix纪元)以来的秒数)。如果tloc
不是NULL,该函数还会将这个时间值存储在tloc
指向的位置。
返回值:成功时返回当前时间(以秒为单位),失败时返回-1。
2. ctime()
函数原型:char *ctime(const time_t *timep);
头文件:<time.h>
功能:将time_t
类型的时间(通常是time()
函数的返回值)转换为本地时间的字符串表示形式。返回的字符串包含了日期和时间,格式通常是“Wed Jun 30 21:49:08 1993\n”。
返回值:指向一个静态分配的字符串的指针,该字符串包含了转换后的时间和日期。由于这个字符串是静态分配的,因此连续调用ctime()
可能会导致之前的返回值被覆盖。
3. localtime()
函数原型:struct tm *localtime(const time_t *timep);
头文件:<time.h>
功能:将time_t
类型的时间(自Unix纪元以来的秒数)转换为本地时间(考虑时区),并以struct tm
结构体的形式返回。
返回值:指向一个struct tm
类型的静态分配对象的指针,该对象包含了转换后的时间信息。和ctime()
一样,由于返回的是静态分配的内存,连续调用可能会覆盖之前的结果。
4. strftime()
函数原型:size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
头文件:<time.h>
功能:根据format
指定的格式,将struct tm
结构体中的时间信息格式化为字符串,并存储在s
指向的数组中。max
参数指定了s
数组的大小,以避免溢出。
返回值:如果成功,返回存储在s
中的字符数(不包括终止的空字符);如果发生错误,返回0。
5. struct tm
定义:struct tm
是一个结构体,用于表示时间信息。它通常包含以下成员(但可能因系统而异):
int tm_sec;
// 秒(0-59)int tm_min;
// 分(0-59)int tm_hour;
// 小时(0-23)int tm_mday;
// 一个月中的第几天(1-31)int tm_mon;
// 月份(0-11,其中0表示1月)int tm_year;
// 年份,自1900年起int tm_wday;
// 一周中的第几天(0-6,其中0表示星期日)int tm_yday;
// 一年中的第几天(0-365,其中0表示1月1日)int tm \_isdst;
// 夏令时标志
进程相关:
1. getpid()
- 头文件:
<unistd.h>
- 参数:无
- 返回值:成功时,返回当前进程的进程ID(PID),一个非负整数。如果出错(虽然这种情况非常罕见),理论上可能会返回-1,但通常不会。
- 功能:获取当前进程的PID。
2. getppid()
- 头文件:
<unistd.h>
- 参数:无
- 返回值:成功时,返回当前进程的父进程ID(PPID),一个非负整数。如果出错(同样非常罕见),可能会返回-1。
- 功能:获取当前进程的父进程的PID。
3. fork()
- 头文件:
<unistd.h>
- 参数:无
- 返回值:
- 在父进程中,返回新创建的子进程的PID。
- 在子进程中,返回0。
- 如果出错,返回-1,并设置
errno
以指示错误。
- 功能:创建一个新的进程,称为子进程,它是调用进程的副本。
4. system()
- 头文件:
<stdlib.h>
- 参数:一个指向以null结尾的字符串的指针,该字符串包含了要执行的shell命令。
- 返回值:
- 命令的终止状态。如果命令成功执行,并且返回了0,则
system()
通常也返回0。 - 如果命令无法被执行,或者
system()
调用失败,则返回-1。注意,system()
的返回值与shell命令的退出状态可能不完全相同,因为system()
还会返回shell本身的退出状态。
- 命令的终止状态。如果命令成功执行,并且返回了0,则
- 功能:执行一个shell命令,并等待命令执行完成。
5. exec
函数族
这些函数用于在当前进程中加载并运行一个新程序,替换当前进程的映像。一旦exec
函数成功执行,当前进程的映像就被新程序替换,因此exec
函数不会返回给调用者。
- 头文件:
<unistd.h>
execl
- 参数:程序路径,参数列表(以
NULL
结尾)。 - 返回值:如果
execl
成功,则不会返回;如果失败,则设置errno
并返回-1(但实际上这个返回值不会被看到,因为进程映像已经被替换)。 - 功能:执行指定路径的程序,并传递参数列表。
execlp
- 参数:程序名(在
PATH
环境变量指定的目录中搜索),参数列表(以NULL
结尾)。 - 返回值和功能:与
execl
相同,但程序名不需要完整路径。
execv
- 参数:程序路径,参数数组(以
NULL
指针结尾)。 - 返回值和功能:与
execl
相同,但参数通过数组传递。
execvp
- 参数:程序名(在
PATH
环境变量指定的目录中搜索),参数数组(以NULL
指针结尾)。 - 返回值和功能:与
execv
相同,但程序名不需要完整路径。
execvpe
- 参数:程序名(在
PATH
环境变量指定的目录中搜索),参数数组(以NULL
指针结尾),环境变量数组(以NULL
指针结尾)。 - 返回值和功能:与
execvp
相同,但允许为新程序指定环境变量。注意,并非所有系统都提供execvpe
函数。
6. wait()
- 头文件:
<sys/wait.h>
(在某些系统中,也可能需要<sys/types.h>
) - 参数:通常是一个指向
int
的指针,用于存储结束的子进程的终止状态;也可以是WAIT_ANY
(在waitpid
中更常见,但wait
通常不使用此值)。 - 返回值:
- 成功时,返回结束的子进程的PID。
- 如果出错,返回-1,并设置
errno
以指示错误。 - 如果
wait()
被信号中断,并且没有指定WNOHANG
选项(wait
函数本身不接受此选项,但waitpid
接受),则行为未定义(但在实践中,它可能会返回-1并设置errno
为EINTR
)。然而,wait
函数通常会在等待子进程时阻塞,直到有子进程结束。
- 功能:等待一个子进程结束,并获取其终止状态。如果有多个子进程,则
wait
会等待任意一个子进程结束。
waitpid():
在 C 语言中,waitpid()
函数的原型通常如下(以 POSIX 标准为例):
#include <sys/wait.h> | |
#include <sys/types.h> | |
pid_t waitpid(pid_t pid, int *status, int options); |
参数
-
pid:指定要等待的子进程的 PID(进程ID)。这个参数有几个特殊的值:
-1
:等待任何一个子进程结束。这相当于wait()
函数的行为,但waitpid()
提供了更多的选项。0
:等待与调用进程属于同一进程组的任何子进程。> 0
:等待其 PID 与参数相等的子进程。< -1
:等待其组 ID 等于参数绝对值且与调用进程属于同一进程组的任何子进程。
-
status:指向整数的指针,用于接收子进程的退出状态。如果此参数不是
NULL
,waitpid()
将把子进程的退出状态写入它所指向的内存位置。这个状态信息可以通过宏函数(如WIFEXITED()
,WEXITSTATUS()
,WIFSIGNALED()
,WTERMSIG()
,WIFSTOPPED()
,WSTOPSIG()
)来解读。 -
options:控制
waitpid()
的行为。这个参数可以是 0 或以下一个或多个常量的按位或组合:WNOHANG
:即使没有任何子进程结束,也立即返回。此时,如果status
不是NULL
且没有子进程结束,则返回 0;如果有子进程结束,则返回该子进程的 PID。WUNTRACED
:如果子进程被停止(例如,由于收到SIGSTOP
、SIGTSTP
、SIGTTIN
或SIGTTOU
信号),也返回其状态。默认情况下,waitpid()
只返回已终止的子进程的状态。
返回值
- 成功时,返回等待的子进程的 PID。
- 如果
WNOHANG
被设置且没有子进程满足条件,则返回 0。 - 如果发生错误,则返回 -1,并设置
errno
以指示错误的原因。
守护进程创建:
1. 创建子进程:fork()
- 功能:
fork()
函数用于创建一个新的进程,称为子进程,它是当前进程的一个副本。 - 返回值:
- 在父进程中,
fork()
返回新创建的子进程的PID。 - 在子进程中,
fork()
返回0。 - 如果出错,则返回-1。
- 在父进程中,
2. 新建会话:setsid()
- 功能:
setsid()
函数用于创建一个新的会话(session),并使调用进程成为该会话的会话首进程(session leader)。同时,调用进程还会脱离任何控制终端(如果有的话)。 - 返回值:
- 成功时,返回会话ID(通常等于调用进程的PID)。
- 如果调用进程已经是会话首进程,则返回-1,并设置
errno
。 - 如果出错,也返回-1,并设置
errno
。
3. 改变工作目录:chdir()
- 功能:
chdir()
函数用于改变当前工作目录到指定的目录。 - 参数:一个指向以null结尾的字符串的指针,该字符串指定了新的工作目录的路径。
- 返回值:
- 成功时,返回0。
- 如果出错,返回-1,并设置
errno
。
守护进程通常会改变其工作目录到根目录(/
),以避免占用可卸载的文件系统。
4. 设置文件模式创建掩码:umask()
- 功能:
umask()
函数用于设置进程的文件模式创建掩码。这个掩码会影响随后创建的文件的权限。 - 参数:一个新的文件模式创建掩码,通常是八进制数。
- 返回值:
- 成功时,返回之前的文件模式创建掩码。
- 如果出错,返回-1,但这种情况很少见。
守护进程通常会设置掩码以确保新创建的文件具有适当的权限。
5. 关闭文件描述符
守护进程需要关闭它从父进程继承的所有不必要的文件描述符,以避免潜在的资源泄露或安全问题。这通常通过遍历文件描述符表并关闭每个描述符来实现,但首先需要知道文件描述符表的大小。
getdtablesize()
:这个函数用于获取进程的文件描述符表的大小(即可以打开的最大文件描述符数)。然而,需要注意的是,getdtablesize()
函数并不是POSIX标准的一部分,而且在许多现代系统上可能不可用或已被废弃。在这些系统上,你可能需要依赖于其他方法(如sysconf(_SC_OPEN_MAX)
)来获取这个值,或者简单地关闭你已知不需要的文件描述符。
进程组
- setpgid(pid_t pid, pid_t pgid)
setpgid
函数用于设置指定进程(pid
)的进程组ID。如果pid
为0,则调用进程(即当前进程)的进程组ID被设置为pgid
。如果pgid
等于0,则调用进程的进程组ID被设置为调用进程的进程ID。这个函数通常用于创建新的进程组或改变现有进程的进程组。
- 注意:这里没有直接列出获取当前进程所属进程组ID的函数,但可以通过调用
getpgid(0)
来获取调用进程所在进程组的ID,其中0
代表当前进程。
会话
- getsid(pid_t pid)
getsid
函数用于获取指定进程(pid
)所在会话的会话ID。会话ID是分配给会话中每个进程的唯一标识符。如果pid
是0,则函数返回调用进程所在会话的会话ID。
- setsid()
setsid
函数用于创建一个新的会话,并成为该会话的会话首进程(session leader)。调用此函数的进程会成为新会话的唯一成员,并且与之前的控制终端(如果有的话)脱离。此外,调用进程的进程组ID和会话ID会被设置为与该进程的进程ID相同,该进程成为新进程组的组长。这个函数通常用于创建守护进程(daemon)或需要脱离控制终端的程序。
系统日志:
1. openlog 函数
openlog
函数用于打开与 syslog 守护进程的连接,并可选地设置日志消息的标识。虽然调用 syslog
之前不强制要求调用 openlog
,但使用 openlog
可以定制日志消息的一些属性。
函数原型:
void openlog(const char *ident, int option, int facility); |
ident
:用于每条日志消息前的标识字符串。如果为 NULL,则使用程序名。option
:控制日志记录行为的选项,如LOG_CONS
、LOG_NDELAY
、LOG_NOWAIT
、LOG_ODELAY
、LOG_PERROR
、LOG_PID
。facility
:用于指定日志消息的来源或类别(如系统守护进程、用户级别消息等)。
2. syslog 函数
syslog
函数用于向系统日志守护进程发送消息。
函数原型:
void syslog(int priority, const char *format, ...); |
priority
:日志消息的优先级,由设施(facility)和级别(level)两部分组成,通过位或操作组合。format
:格式字符串,类似于printf
的格式字符串。...
:与format
对应的参数列表。
3. closelog 函数
closelog
函数用于关闭与 syslog 守护进程的连接。不过,在程序正常结束时,这个调用通常是可选的,因为系统会在程序退出时自动清理资源。
函数原型:
void closelog(void); |
系统日志优先级;
进程的终止:
正常终止
- 主函数
return
:- 当主函数(通常是
main
函数)执行到return
语句时,程序会正常结束。返回给操作系统的值通常用于指示程序的退出状态(成功或某种形式的错误)。
- 当主函数(通常是
- 调用
exit
:exit
函数用于正常终止程序,并可以指定一个退出状态给操作系统。它会执行一些清理工作,包括调用所有已注册的atexit
函数,关闭所有打开的文件描述符(如果有的话),清空并关闭stdout
和stderr
缓冲区(但请注意,这并不意味着它会“清空”stdout
的内容,而是确保所有缓冲的输出都被刷新到终端或文件中)。
- 调用
_exit
:_exit
函数也用于终止程序,但它不执行任何清理操作,如关闭文件描述符或调用atexit
函数。它直接退出程序,并将控制权返回给操作系统,因此不会清空stdout
缓冲区。这通常用于在程序已经严重损坏或处于不安全状态时快速退出。
异常终止
kill
命令:kill
命令用于向指定的进程发送信号。如果发送的信号是终止信号(如 SIGTERM 或 SIGKILL),则会导致进程异常终止。SIGTERM 请求进程终止,但允许它进行清理操作;而 SIGKILL 强制立即终止进程,不允许进行任何清理。
- 主动异常终止
abort
:abort
函数用于生成一个 SIGABRT 信号,该信号通常用于指示程序中的严重错误,如断言失败。接收到 SIGABRT 信号后,程序会异常终止,并可能生成一个核心转储文件(取决于操作系统的配置),用于调试。
- 另一个进程或硬件信号终止:
- 除了
kill
命令发送的信号外,程序还可能因为接收到来自其他进程的信号或硬件事件(如非法内存访问)而异常终止。这些信号包括但不限于 SIGINT(通常由 Ctrl+C 触发)、SIGSEGV(段错误)、SIGFPE(浮点异常)等。接收到这些信号后,程序通常会立即终止,除非有信号处理函数被注册来捕获并处理这些信号。
- 除了
线程相关:
线程库:NPTL
1. 线程创建:pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, | |
void *(*start_routine) (void *), void *arg); |
- 功能:创建一个新线程,该线程执行由
start_routine
指定的函数,arg
作为该函数的参数。 - 参数:
thread
:指向pthread_t类型的指针,用于存储新线程的标识符。attr
:指向线程属性对象的指针,可以指定线程的各种属性,如堆栈大小、调度策略等。如果为NULL,则使用默认属性。start_routine
:新线程将要执行的函数。arg
:传递给start_routine
函数的参数。
- 返回值:成功时返回0,失败时返回错误码。
2. 查看当前线程ID:pthread_self
pthread_t pthread_self(void); |
- 功能:返回调用线程的线程ID。
- 返回值:调用线程的线程ID。
3. 等待线程结束:pthread_join
int pthread_join(pthread_t thread, void **retval); |
- 功能:等待指定的线程结束。如果
retval
不为NULL,则线程的返回值将被存储在retval
指向的位置。 - 参数:
thread
:要等待的线程的线程ID。retval
:用于存储线程返回值的指针的地址。如果不需要,可以设置为NULL。
- 返回值:成功时返回0,失败时返回错误码。
4. 分离线程:pthread_detach
int pthread_detach(pthread_t thread); |
- 功能:将指定的线程设置为“分离”状态,这样当线程结束时,其资源会自动释放,而不需要其他线程来调用
pthread_join
。 - 参数:
thread
:要设置为分离状态的线程的线程ID。
- 返回值:成功时返回0,失败时返回错误码。
5. 线程退出:pthread_exit
void pthread_exit(void *retval); |
- 功能:终止调用线程的执行。如果线程创建了子线程,并且这些子线程尚未被分离或等待,则这些子线程将不会被终止。
- 参数:
retval
:线程的返回值,其他线程可以通过pthread_join
获取。
- 注意:一旦调用了
pthread_exit
,线程将不再执行任何代码。
6. 取消线程:pthread_cancel
int pthread_cancel(pthread_t thread); |
- 功能:向指定的线程发送取消请求。线程是否响应取消请求取决于其取消状态和取消类型。
- 参数:
thread
:要取消的线程的线程ID。
- 返回值:成功时返回0,失败时返回错误码。
- 注意:线程可以通过设置取消状态和取消类型来忽略取消请求,或者通过调用
pthread_testcancel
来检查是否有取消请求并响应它。
7.手动添加取消点
1. pthread_testcancel
功能:pthread_testcancel
函数用于测试调用线程是否应该被取消。如果线程被设置了取消状态(即,其他线程对该线程调用了 pthread_cancel
),并且该线程没有禁用取消(通过 pthread_setcancelstate
),则 pthread_testcancel
会导致线程被取消,就像执行了一个异步取消请求一样。
头文件:
#include <pthread.h> |
返回值:
- 成功时,该函数不返回(因为线程被取消)。
- 如果线程没有被取消,则该函数正常返回。
参数:
无参数。
注意事项:
- 线程应定期调用
pthread_testcancel
以确保能够及时响应取消请求。 - 取消是协作的,意味着线程必须主动检查取消状态(通过
pthread_testcancel
)或执行可能被取消的点(如某些库函数)。
8. 资源清理栈 (pthread_cleanup_push
和 pthread_cleanup_pop
)
功能:
资源清理栈用于在线程取消或退出时自动执行清理操作(如释放资源、关闭文件等)。pthread_cleanup_push
用于将清理函数压入栈中,而 pthread_cleanup_pop
用于从栈中移除清理函数,并可选择性地执行它。
头文件:
#include <pthread.h> |
pthread_cleanup_push
返回值:
- 无返回值(宏定义,非函数)。
pthread_cleanup_pop
返回值:
- 成功时返回 0。
- 出错时返回错误码。
参数:
pthread_cleanup_push(void (*routine)(void *), void *arg)
:routine
:指向清理函数的指针。arg
:传递给清理函数的参数。
pthread_cleanup_pop(int execute)
:execute
:如果非 0,则执行栈顶的清理函数;如果为 0,则不执行。
注意事项:
- 清理函数应设计为可重入的,因为可能在多线程环境中被调用。
- 使用
pthread_cleanup_push
和pthread_cleanup_pop
时,通常将pthread_cleanup_push
放在代码块的开始,pthread_cleanup_pop
放在结束(无论是正常退出还是通过异常路径)。 - 如果在
pthread_cleanup_pop
调用之前线程被取消,则栈上所有未执行的清理函数都将被执行。 - 清理函数不应调用任何可能导致线程取消的函数,因为这可能导致死锁或未定义行为。
同步互斥机制:
同步 - 无名信号量
头文件:<semaphore.h>
(注意,在某些系统中可能需要链接实时库,如-lrt
)
sem_init
- 功能:初始化一个未命名的信号量。
- 参数:
sem
:指向信号量结构的指针。pshared
:如果非0,信号量将在进程间共享;如果为0,信号量仅在当前进程的线程间共享。value
:信号量的初始值。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
sem_wait
- 功能:等待(阻塞)信号量的值大于0。如果信号量的值为0,则调用线程将被阻塞,直到信号量的值大于0。操作成功后,信号量的值减1。
- 参数:
sem
:指向信号量结构的指针。 - 返回值:成功时返回0;失败时返回-1,并设置errno。
sem_post
- 功能:增加信号量的值。如果信号量的值从0增加到1,则可能唤醒一个等待该信号量的线程。
- 参数:
sem
:指向信号量结构的指针。 - 返回值:成功时返回0;失败时返回-1,并设置errno。
同步 - 有名信号量
头文件:<sys/sem.h>
,但注意,在现代Linux系统中,通常推荐使用POSIX信号量(即无名信号量),因为semget
、semop
、semctl
等函数是System V信号量的API,它们较老且不如POSIX信号量灵活。
semget
- 功能:创建一个新的信号量集或访问一个已存在的信号量集。
- 参数:
key
:用于创建新信号量集的唯一标识符。nsems
:信号量集中的信号量数量。semflg
:控制信号量集创建的标志。
- 返回值:成功时返回信号量集的标识符;失败时返回-1,并设置errno。
semop
- 功能:对信号量集中的信号量执行操作。
- 参数:
semid
:信号量集的标识符。sops
:指向sembuf
结构的数组,指定了要执行的操作。nsops
:sops
数组中元素的数量。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
semctl
- 功能:用于对信号量集执行各种控制操作,如获取信号量的值、设置信号量的值、初始化信号量集等。
- 参数:
semid
:信号量集的标识符。semnum
:信号量集中的信号量编号(从0开始)。cmd
:要执行的控制命令。arg
:根据cmd
的不同,这个参数可以是不同的类型,如信号量的新值、指向union semun
的指针等。
- 返回值:根据
cmd
的不同,返回值也有所不同。对于大多数命令,成功时返回0;失败时返回-1,并设置errno。
互斥
头文件:<pthread.h>
pthread_mutex_init
- 功能:初始化一个互斥锁。
- 参数:
mutex
:指向互斥锁变量的指针。attr
:用于指定互斥锁属性的指针,如果为NULL,则使用默认属性。
- 返回值:成功时返回0;失败时返回错误码。
pthread_mutex_lock
- 功能:尝试对互斥锁加锁。如果互斥锁已被锁定,则调用线程将被阻塞,直到互斥锁被解锁。
- 参数:
mutex
:指向互斥锁变量的指针。 - 返回值:成功时返回0;失败时返回错误码。
pthread_mutex_unlock
- 功能:对互斥锁进行解锁。
- 参数:
mutex
:指向互斥锁变量的指针。 - 返回值:成功时返回0;失败时返回错误码。
pthread_mutex_destroy
- 功能:销毁一个互斥锁。在销毁之前,必须确保互斥锁是未锁定的状态。
- 参数:
mutex
:指向互斥锁变量的指针。 - 返回值:成功时返回0;失败时返回错误码。
通信机制:
system V :
命令:ipcs ,,ipcrm
- 函数原型:
key_t ftok(const char *pathname, int proj_id);
- 头文件:
<sys/ipc.h>
参数说明
- pathname:指向文件路径的指针。这个文件通常是项目中的一个已知文件,但它不需要实际存在,但必须是唯一的,以便在不同的项目或实例中生成不同的键。不过,在大多数实际使用中,为了确保键的唯一性和稳定性,通常会指定一个确实存在的文件。
- proj_id:一个8位(1字节)的整数,用于进一步区分同一路径下的不同键。这个值通常是项目的唯一标识符,但在实际应用中,它可以是任何非零的整数值。
返回值
- 如果成功,ftok函数返回一个唯一的键(key_t类型)。
- 如果失败,返回-1,并设置errno以指示错误。可能的错误包括EACCES(调用进程对pathname没有读权限)、ENOENT(pathname指定的文件或目录不存在)、ENOMEM(没有足够的内存来执行操作)和EINVAL(pathname不指向一个文件或目录)。
管道
有名管道
- mkfifo
- 头文件:
<sys/stat.h>
和<fcntl.h>
- 功能:创建一个有名管道。
- 参数:
pathname
:管道的文件名。mode
:管道文件的权限,类似于open
函数的mode
参数。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
- 头文件:
匿名管道
- pipe函数
- 头文件:
<unistd.h>
- 功能:创建一个匿名管道,用于父子进程或相关进程间的通信。
- 参数:
filedes
:指向一个包含两个文件描述符的数组,第一个用于读,第二个用于写。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
- 头文件:
消息队列
- msgget
- 头文件:
<sys/ipc.h>
和<sys/msg.h>
- 功能:创建或访问一个消息队列。
- 参数:
key
:用于创建或访问消息队列的键。msgflg
:控制消息队列创建和访问的标志。
- 返回值:成功时返回消息队列的标识符;失败时返回-1,并设置errno。
- 头文件:
- msgsnd
- 功能:向消息队列发送消息。
- 参数:
msqid
:消息队列的标识符。msgp
:指向消息缓冲区的指针。msgsz
:消息的大小(不包括消息类型字段)。msgflg
:控制消息发送的标志。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
- msgrcv
- 功能:从消息队列接收消息。
- 参数:
msqid
:消息队列的标识符。msgp
:指向消息缓冲区的指针。msgsz
:消息缓冲区的最大大小。msgtyp
:请求的消息类型。msgflg
:控制消息接收的标志。
- 返回值:成功时返回接收到的消息的实际字节数;失败时返回-1,并设置errno。
- msgctl
- 功能:执行消息队列的控制操作,如删除队列。
- 参数:
msqid
:消息队列的标识符。cmd
:要执行的控制命令。buf
:指向msqid_ds
结构的指针,用于某些命令。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
共享内存
- shmget
- 功能:创建或访问一个共享内存段。
- 参数:
key
:用于创建或访问共享内存段的键。size
:共享内存段的大小。shmflg
:控制共享内存段创建和访问的标志。
- 返回值:成功时返回共享内存段的标识符;失败时返回-1,并设置errno。
- shmat
- 功能:将共享内存段连接到进程的地址空间。
- 参数:
shmid
:共享内存段的标识符。shmaddr
:建议的附加地址(通常为NULL)。shmflg
:控制附加操作的标志。
- 返回值:成功时返回共享内存段附加到进程地址空间的地址;失败时返回(void *)-1,并设置errno。
- shmdt
- 功能:断开共享内存段与进程的连接。
- 参数:
shmaddr
:共享内存段附加到进程地址空间的地址。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
- shmctl
- 功能:执行共享内存段的控制操作,如删除共享内存段。
- 参数:
shmid
:共享内存段的标识符。cmd
:要执行的控制命令。buf
:指向shmid_ds
结构的指针,用于某些命令。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
信号---(阻塞未决等信息另一篇有提到这里不详解)
- kill
- 头文件:
<signal.h>
- 功能:向进程发送信号。
- 参数:
pid
:接收信号的进程的PID。sig
:要发送的信号。
- 返回值:成功时返回0;失败时返回-1,并设置errno。
- 头文件:
- raise
- 功能:向当前进程发送信号。
- 参数:
sig
:要发送的信号。
- 返回值:成功时返回0;失败时返回非0值,并设置errno。
- abort
- 功能:导致程序异常终止,并向进程发送SIGABRT信号。
- 参数:无。
- 返回值:不返回。
更改信号的默认行为:
signal 函数
返回值
- 成功时返回之前的信号处理函数指针(如果成功查询)或0(如果成功设置)。
- 失败时返回SIG_ERR,并设置errno以指示错误。
头文件
<signal.h>
功能
- 设置或查询与特定信号相关联的处理函数。
参数
int signum
:要处理的信号编号。void (*handler)(int)
:指向新信号处理函数的指针,或者SIG_IGN(忽略信号)、SIG_DFL(恢复信号的默认处理行为)等特殊值。
#include <signal.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
void signal_handler(int signum) { | |
printf("Caught signal %d\n", signum); | |
// 清理代码... | |
exit(signum); | |
} | |
int main() { | |
// 设置SIGINT信号的处理函数 | |
signal(SIGINT, signal_handler); | |
// 无限循环,等待信号 | |
while(1) { | |
pause(); // 使进程暂停直到接收到信号 | |
} | |
return 0; | |
} |
1. sigemptyset
功能:初始化信号集,将其中的所有信号都设置为未选择状态。
头文件:<signal.h>
原型:int sigemptyset(sigset_t *set);
参数:
set
:指向信号集的指针,该信号集将被初始化为不包含任何信号的集合。
返回值:成功时返回0;失败时返回-1,并设置errno以指示错误。
2. sigaddset
功能:向信号集中添加一个信号。
头文件:<signal.h>
原型:int sigaddset(sigset_t *set, int signum);
参数:
set
:指向信号集的指针。signum
:要添加到信号集中的信号编号。
返回值:成功时返回0;失败时返回-1,并设置errno以指示错误。
3. sigdelset
功能:从信号集中删除一个信号。
头文件:<signal.h>
原型:int sigdelset(sigset_t *set, int signum);
参数:
set
:指向信号集的指针。signum
:要从信号集中删除的信号编号。
返回值:成功时返回0;失败时返回-1,并设置errno以指示错误。
4. sigaction
功能:查询或更改与特定信号相关联的动作。
头文件:<signal.h>
原型:int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
参数:
sig
:指定要更改或查询其行为的信号编号。act
:如果非NULL,则指向一个sigaction结构体,该结构体指定了新信号处理器及其相关标志。oact
:如果非NULL,则指向一个sigaction结构体,该结构体将包含调用前的信号处理器及其相关标志。
sigaction结构体:
sa_handler
:指向信号处理函数的指针,或使用SIG_IGN忽略信号,或使用SIG_DFL恢复默认行为。sa_sigaction
:指向一个接受额外信息的信号处理函数的指针(SA_SIGINFO标志)。sa_mask
:一个信号集,指定了在执行信号处理函数期间应被阻塞的信号。sa_flags
:指定信号处理选项的位掩码。
返回值:成功时返回0;失败时返回-1,并设置errno以指示错误。
网络(下一篇网络详解,这里只做略)
- socket
- 头文件:
<sys/socket.h>
- 功能:创建一个新的套接字。
- 参数:
domain
:协议族(如AF_INET)。type
:套接字类型(如SOCK_STREAM)。protocol
:特定于协议的选项(通常为0)。
- 返回值:成功时返回套接字的文件描述符;失败时返回-1,并设置errno。
- 头文件: