為什麼unix和linux里的函數前面都有一個 『f』 ?
如題,
最近在看unix環境高級編程,發現裡面很多函數前面都有一個f,比如fopen,ftruncate,fstat, fchown等,而且不要『f』又是一套函數,我網上也沒搜到有什麼具體含義。
f 一般是 file 或 fd 的意思。不過 Unix 的庫函數和系統調用的命名很混亂,題主舉的幾個例子其實有兩種情況:
open/fopen:open 是 syscall 的名字,fopen 是 C 庫函數的名字。為了避免和 syscall 名字衝突,C 庫函數里的 wrapper 很多都帶 f 前綴。其實還有一種情況就是不帶 f 的是作用在 stdin/stdout 上的帶 f 的作用在 FILE* 上……
剩下的:不帶 f 的第一個參數是路徑,帶 f 的第一個參數是 fd。先列出APUE書中第3,4,5章中出現的所有關於文件操作的函數吧。
第三章
文件IO--無緩衝IO
#include
&
int
open(const char *pathname, int oflag, ... /* mode_t mode
*/ );
int
creat(const char *pathname, mode_t mode);
int
fcntl(int filedes, int cmd, ... /* int arg */ );
#include
&
int
close(int filedes);
off_t
lseek(int filedes, off_t offset, int whence);
ssize_t
read(int filedes, void *buf, size_t nbytes);
ssize_t
write(int filedes, const void *buf, size_t nbytes);
ssize_t
pread(int filedes, void *buf, size_t nbytes, off_t offset);
ssize_t
pwrite(int filedes, const void *buf,
size_t nbytes, off_t offset);
int
dup(int filedes);
int
dup2(int filedes, int filedes2);
int
fsync(int filedes);
int
fdatasync(int filedes);
void
sync(void);
#include
&
int
ioctl(int filedes, int request, ...);
第四章
文件和文件夾
#include
&
int
stat(const char *restrict pathname, struct stat *restrict buf);
int
fstat(int filedes, struct stat *buf);
int
lstat(const char *restrict pathname, struct stat *restrict buf);
mode_t
umask(mode_t cmask);
int
chmod(const char *pathname, mode_t mode);
int
fchmod(int filedes, mode_t mode);
int
mkdir(const char *pathname, mode_t mode);
#include
&
int
access(const char *pathname, int mode);
int
chown(const char *pathname, uid_t owner, gid_t group);
int
fchown(int filedes, uid_t owner, gid_t group);
int
lchown(const char *pathname, uid_t owner,
gid_t group);
int
truncate(const char *pathname, off_t length);
int
ftruncate(int filedes, off_t length);
int
link(const char *existingpath, const char *newpath);
int
unlink(const char *pathname);
int
symlink(const char *actualpath, const char *sympath);
ssize_t
readlink(const char* restrict pathname,
char *restrict buf,
size_t
bufsize);
int
rmdir(const char *pathname);
int
chdir(const char *pathname);
int
fchdir(int filedes);
char
*getcwd(char *buf, size_t size);
#include
&
int
utime(const char *pathname, const struct utimbuf *times);
#include
&
DIR
*opendir(const char *pathname);
struct
dirent *readdir(DIR *dp);
void
rewinddir(DIR *dp);
int
closedir(DIR *dp);
long
telldir(DIR *dp);
void
seekdir(DIR *dp, long loc);
#include &
int remove(const char *pathname);
int rename(const char *oldname, const char *newname);
第五章
標準IO
#include
&
int
fwide(FILE *fp, int mode);
void
setbuf(FILE *restrict fp, char *restrict buf);
int
setvbuf(FILE *restrict fp, char *restrict buf,
int mode,
size_t
size);
int
fflush(FILE *fp);
FILE
*fopen(const char *restrict pathname, const char *restrict type);
FILE
*freopen(const char *restrict pathname, const char *restrict type,
FILE *restrict fp);
FILE
*fdopen(int filedes, const char *type);
int
fclose(FILE *fp);
int
ungetc(int c, FILE *fp);
int
getc(FILE *fp);
int
fgetc(FILE *fp);
int
getchar(void);
char
*fgets(char *restrict buf, int n, FILE *restrict fp);
char
*gets(char *buf);
int
ferror(FILE *fp);
int
feof(FILE *fp);
void
clearerr(FILE *fp);
int
putc(int c, FILE *fp);
int
fputc(int c, FILE *fp);
int
putchar(int c);
int
fputs(const char *restrict str, FILE *restrict fp);
int
puts(const char *str);
size_t
fread(void *restrict ptr, size_t size,
size_t nobj,
FILE *restrict
fp);
size_t
fwrite(const void *restrict ptr, size_t size, size_t nobj,
FILE
*restrict fp);
long
ftell(FILE *fp);
int
fseek(FILE *fp, long offset, int whence);
void
rewind(FILE *fp);
off_t
ftello(FILE *fp);
int
fseeko(FILE *fp, off_t offset, int whence);
int
fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int
fsetpos(FILE *fp, const fpos_t *pos);
int
printf(const char *restrict format, ...);
int
fprintf(FILE *restrict fp, const char *restrict format, ...);
int
sprintf(char *restrict buf, const char *restrict format, ...);
int
snprintf(char *restrict buf, size_t n,
const char *restrict format,
...);
int
vprintf(const char *restrict format, va_list arg);
int
vfprintf(FILE *restrict fp, const char *restrict format,
va_list
arg);
int
vsprintf(char *restrict buf, const char *restrict format,
va_list
arg);
int
vsnprintf(char *restrict buf, size_t n,
const char *restrict format,
va_list arg);
int
scanf(const char *restrict format, ...);
int
fscanf(FILE *restrict fp, const char *restrict format, ...);
int
sscanf(const char *restrict buf, const char *restrict format,
...);
int
vscanf(const char *restrict format, va_list arg);
int
vfscanf(FILE *restrict fp, const char *restrict format,
va_list
arg);
int
vsscanf(const char *restrict buf, const char *restrict format,
va_list arg);
int
fileno(FILE *fp);
char
*tmpnam(char *ptr);
FILE
*tmpfile(void);
char
*tempnam(const char *directory, const char *prefix);
int
mkstemp(char *template);
- 系統提供的文件操作
根據上述列表可以看到,第3章全部以及第4章的大部分(除了第4章的最後remove和rename兩個函數)都是系統提供的文件操作。
第三章中出現f的函數有3個:int fcntl(int filedes, int cmd, ... /* int arg */ );int fsync(int filedes);
int fdatasync(int filedes);
而這三個函數中只有fsync有一個沒有f的同名函數sync,前者是同步某個文件,而後者是同步該進程中的所有文件。其他兩個並沒有不帶f的同名函數,這裡只能猜測,加上f更容易讓人理解,這是針對文件的操作。
第四章中出現f的函數就比較容易區分了,因為所有帶f的函數都有一個與之匹配的不帶f的函數,而帶f的函數是以文件描述符作為參數,不帶f的函數則是以文件路徑作為參數。
通過以上觀察,可以得出如下結論:
系統提供的基本上是不帶f的函數來表示文件操作,而只有含有同名函數時,為了加以區分,將以文件描述符為參數的函數添加上f,而以文件路徑為參數的函數不加f。
- 標準庫提供的文件操作
標準庫中的函數大部分都帶f,而僅當操作標準輸入/輸出時,不帶f。其中幾個例外列於下邊:
void setbuf(FILE *restrict fp, char *restrict buf);
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
int ungetc(int c, FILE *fp);
int getc(FILE *fp);
int putc(int c, FILE *fp);
void rewind(FILE *fp);
void clearerr(FILE *fp);
以上這些函數都有一個FILE*類型的流fp,卻沒有添加f,用粗體標註的兩個函數和帶f的函數功能一樣,僅僅實現不同,這兩者可以使用宏來實現,而fgetc和fputc是不可以用宏實現的。其他幾個只能說這樣命名沒有歧義,並且不與系統調用衝突,且簡練(lan)。
linux系統 一切都可看做是 文件 操作 。有這麼一種說法
推薦閱讀:
※網路編程(三):從libevent到事件通知機制
※Linux的目錄結構是否過於複雜難懂,不夠清晰直觀?
※電腦複製粘貼背後發生了什麼?
※正在學習嵌入式linux開發,求推薦詳細介紹makefile和鏈接腳本語法相關的書籍或者資料。?
※一個用慣了windows的用戶,怎樣上手linux系統?如果用linux系統,能夠勝任日常辦公需求嗎?
TAG:Linux | Unix | UNIX環境高級編程書籍 |