=========================================================================================
[1] >> 文件?
[
<√> 目录文件--d = directory
<√> 字符设备文件--c = char
<√> 块设备文件--b = block
<√> 管道文件--p = pipe
<√> 套接字文件--s = socket
<√> 符号链接文件--l = ln
]
=========================================================================================
[2] >> 文件流FILE?
-->>流程讲解:将"word11 word12"写到text1.txt的"word8"后面
--------------------------------------------------------------------------------------------
SEEK_SET======⇳ 文件text1.txt
[word1 word2 word3 ]
[word4 word5 word7 ] 缓冲区队列/文件流
[word8 word9 word10 EOF] =======[word11 word12 ] <--> 输入设备
[ ⇳ ⇳ ⇳ ] ⇳
[ ⇳ ⇳ ⇳ ] ⇳
⇳ ⇳ =====文件结束符 ⇳
SEEK_CUR SEEK_END ⇳
⇳ ⇳
====================================
<√>
<√>
<√>
<√>
--------------------------------------------------------------------------------------------
-->>系统预定义文件流:
[
<√> 标准输入流 STDIN_FILENO stdin 0
<√> 标准输出流 STDOUT_FILENO stdout 1
<√> 标准错误流 STDERR_FILENO stderr 2
]
<√>-->>FILE*fopen(const char *path,const char*mode); [r/r+/w/w+/a/a+,a=append=文件末尾写] [return :NULL --> error]
<√>-->>int fclose(FILE*stream); [EOF = error]
<√>-->>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); [return:the number of items successfully read ;0 is error or end of file]
<√>-->>size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);[return:the number of items successfully written ; 0 is error or end of file]
<√>-->>int fflush (FILE *fp); [EOF-->error] [流满,换行,fflush --> 写入文件(效率高)]
<√>-->>long ftell(FILE *stream); [得到文件内部位置指针的位置 : 数据流被fflush到文件内部位置指针的后面] [return : -1--> error]
<√>-->>int fprintf(FILE *stream, const char *format, ...);[return : 写入的字节个数]
<√>-->>int feof(FILE *stream);[检测流上的文件结束符,通常判断是否读到文件末尾] [return:0-->未末尾;!0-->末末尾]
<x>-->>long fseek(FILE *stream,long offset, int whence);[return : 0-->success ;-1 --> error]
<√>-->>打开ubuntu串口终端(ctrl + alt + fn) ; 切换到ubuntu桌面(ctrl + alt + f7)
<√>[SEEK_SET 文件开头]
<√>[SEEK_CUR 文件当前]
<√>[SEEK_END 文件末尾]
<√>[重定位文件内部位置指针]
<√>[后续数据写入将在位置指针后面接入]
-->>注意:fread与fwrite不能同时在一个流里面操作,因为流是单向的,必须写完后,关闭流后,再重新打开文件流进行读取
============================================================================================================
[3] >> 其他重要函数?
<√>-->>void perror(const char *s); [能自动输出错误信息]
<√>-->>int sprintf(char *str, const char *format, ...); [return : 写入的字节数]
==============================================================================================
[4] >> Linux系统提供的文件IO接口 ?
<√>-->>没有流缓冲区机制,返回文件描述符fd
<√>-->>文件IO函数功能更强大,能打开更多种类文件 [文件流只能打开普通文件]
<√>-->>int open(constchar*pathname,int flags); [0=stdin;1=stdout;2=error;后续打开文件分配3.4.5.....] [return:-1 --> error]
[flags参数:
<√>O_RDONLY只读模式
<√>O_WRONLY只写模式
<√>O_RDWR读写模式
<√>O_APPEND每次写操作都写入文件的末尾
<x>O_CREAT如果指定文件不存在,则创建这个文件
<√>O_EXCL如果要创建的文件已存在,则返回-1,并且修改errno的值
<x>O_NONBLOCK or O_NDELAY表示非阻塞模式
]
<√>-->>ssize_t write(int fd, const void *buf, size_t count); [-1-->error]
<√>-->>ssize_t read(int fd, void *buf, size_t count); [-1-->error]
<√>-->>off_t lseek(int fd, off_t offset, int whence); [-1 --> error]
<√>[SEEK_SET 文件开头]
<√>[SEEK_CUR 文件当前]
<√>[SEEK_END 文件末尾]
<√>[重定位文件内部位置指针]
<√>[如果执行成功,后续数据将写入以whence为基准,偏移offset(指针偏移量)个字节的位置]
<√>-->>int close(int fd); [-1-->error]
<x>-->>注意:read,write不能同时进行,必须fd关闭再操作
==================================================================================================
==================================================================================================
[5] >> 目录流DIR ?
<√>-->>目录(directory)
-->>目录流操作流程:
[file/目录下有如下9个文件]
⇳
⇳ DIR(第一次readdir)
⇳ ⇳ DIR(第2次readdir)
⇳ ⇳ ⇳ DIR(第3次readdir)
⇳ ⇳ ⇳ ⇳
file/ -->>[text1.c text2.c text3.c]
[text4.c text5.c text6.c]
[text7.c text8.c text9.c]
<√>-->>DIR *opendir(const char *name); [NULL --> error]
<x:>-->>struct dirent *readdir(DIR *dirp); [NULL --> error]
[
struct dirent {
ino_t d_ino;
off_t d_off; <√>
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
]
<√>-->>int closedir(DIR *dirp); [return : -1 -->error;]
==================================================================================================
[6] >> 库
<√>-->> /lib 存放动态库文件
<√>-->> /usr/lib 用户程序的库文件
<√>-->>静态库文件格式:lib名称.a
[
<√>ar -crs libtext.a text.o [ar建立档案]
<√>nm libtext.a [list symbols from object files]
<√>gcc main.o -L -l libtext.a [-L+库路径 ; -l+库名 ; -I+头文件路径]
]
<√>-->>动态库文件格式:lib名称.so
[
<x>gcc -c -fPIC text.c [表示编译为位置独立的代码]
<x>gcc text.o -shared -o libtext.so
<√>nm libtext.so
<√>gcc main.o -L -l libtext.so [L--路径 ; l--库名]
]
==================================================================================================
[7] >> system v IPC ?
<√>-->>[IPC = in process communicate ] [system = 系统 = 内核中]
<√>-->>IPC = {
共享内存(shm)、消息队列(msg)和信号量(sem)}
<√>-->>ipcs命令 [显示所有IPC对象]
<√>-->>ipcs -l [查看最大IPC空间是多少]
<√>-->>ipcrm [-M -m -S -s -Q -q] [key值 id值]
[
ipcrm -M key 根据key删除内存类型ipc
ipcrm -m id根据pic号删除内存型ipc
ipcrm -Q key根据键值删除队列ipc
ipcrm -q id根据pic号删除队列型ipc
ipcrm -S key根据键值删除信号量ipc
ipcrm -s id根据pic号删除信号量ipc
]
[
================================================================================================================
<x>共享内存是Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
[
<√>1>>key_t ftok(const char *pathname, int proj_id);
[
id是子序号。虽然是int类型,但是只使用8bits(1-255)。
在一般的UNIX实现中,是将文件的索引号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002
]
<√>2>>int shmget(key_t key, size_t size, int shmflg);[return :-1 --> error;]
[
函数说明--得到/创建一个共享内存对象并返回共享内存标识符
函数传入值
key -- 0(IPC_PRIVATE):会建立新共享内存对象 / ftok返回的IPC键值
size -- 大于0的整数:新建的共享内存大小,以字节为单位 / 0:只获取共享内存时指定为0 [ipcs -l]
shmflg
0:取共享内存标识符
IPC_CREAT:创建新的消息队列
IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
成功:返回共享内存的标识符
出错:-1,错误原因存于errno中
]
<√>3>>void *shmat(int shmid, const void *shmaddr, int shmflg);
[
函数说明--连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
函数传入值
shmid--共享内存标识符
shmaddr--指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg--SHM_RDONLY:为只读模式,其他为读写模式
函数返回值
成功:附加好的共享内存地址
出错:-1,错误原因存于errno中
]
<√>4>>int sprintf(char *str, const char *format, ...);
<√>5>>int printf(const char *format, ...); [return : -1-->error]
<x>6>>int shmdt(void*shmaddr); [return:-1-->error;]
<x>7>>int shmctl(int shmid, int cmd, struct shmid_ds *buf);[return:-1-->error;0-->success]
[
函数说明--完成对共享内存的控制
函数传入值
shmid--共享内存标识符
cmd
IPC_STAT--得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET--改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID--删除这片共享内存
buf--共享内存管理结构体
函数返回值
成功:0
出错:-1,错误原因存于error中
]
]
========================================================================================================
消息队列
[
-->>消息队列的使用流程
[
<√>1>>key_t ftok(const char *pathname, int proj_id);[前面已介绍]
<x>2>>int msgget(key_t key, int msgflg);
[
功能--用于创建一个新的或打开一个已经存在的消息队列,此消息队列与key相对应
key--函数ftok的返回值或IPC_PRIVATE
msgflag
IPC_CREAT:创建新的消息队列
IPC_CREAT值,若没有该队列,则创建一个并返回新标识符;若已存在,则返回原标识符。
IPC_EXCL值,若没有该队列,则返回-1;若已存在,则返回0。
返回值--调用成功返回队列标识符,否则返回-1.
]
<x>3>>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);[return:-1-->error;0-->success]
[
功能--将一个新的消息写入队列
msqid--队列标识符
msgp
struct msgbuf {
long mtype;
char mtext[1];
};
msgsz--msgp结构体大小
msgflg:这个参数依然是控制函数行为的标志
0--表示忽略;
IPC_NOWAIT--如果消息队列为空,则立即返回一个ENOMSG,并将控制权交回调用函数的进程。
成功执行--返回0,失败返回-1
]
<x>4>>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);[return:-1-->error;接收到的字节数]
[
功能--从消息队列中读取消息,从消息队列发送结构体搬运到接收结构体
msqid--队列标识符
msgp
struct msgbuf {
long mtype;
char mtext[1];
};
msgsz--结构体大小
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为msgtyp的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
]
<√>5>>int msgctl(int msqid, int cmd, struct msqid_ds *buf);[ds = data =struct] [-1 ---> error]
[
msqid--队列标识符
cmd
IPC_STAT--读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中。
IPC_SET--设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
I PC_RMID--从系统内核中移走消息队列。
0 ,如果成功;- 1,如果失败:
]
]
========================================================================================================
信号量数组
[
-->>信号灯使用步骤
<√>1>>key_t ftok(const char *pathname, int proj_id); [前面已经介绍]
<√>2>>int semget(key_t key, int nsems, int semflg);
[
key--所创建或打开信号量集的键值。
nsems--创建的信号量集中的信号量的个数,该参数只在创建信号量集时有效。
semflg--调用函数的操作类型
-1--error
]
<x>3>>int semctl(int semid, int semnum, int cmd, …);
[
功能--信号量数组中的某个信号量的操作(赋初值,删除...)
semid--信号量数组标识符
semnum--操作信号量数组的第几个信号量
cmd
IPC_SET -- 信号量数组中第semnum个信号量赋值为semun.val
IPC_RMID
IPC_STAT
返回值:如果成功,则为一个正数。如果失败,则为-1
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;