IO进程
2023-09-09 09:58:14 0 举报
AI智能生成
IO进程函数总结
作者其他创作
大纲/内容
文件IO
函数
open、close
int open(const char *pathname, int flags);
功能:打开文件
参数:pathname:文件路径名
flags:打开文件的方式
O_RDONLY:只读 O_WRONLY:只写 O_RDWR:可读可写 O_CREAT:创建 O_TRUNC:清空
O_APPEND:追加
返回值:成功:文件描述符
失败:-1
当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname, int flags, mode_t mode);
创建出来的文件权限为指定权限值&(~umask) //umask为文件权限掩码
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
功能:打开文件
参数:pathname:文件路径名
flags:打开文件的方式
O_RDONLY:只读 O_WRONLY:只写 O_RDWR:可读可写 O_CREAT:创建 O_TRUNC:清空
O_APPEND:追加
返回值:成功:文件描述符
失败:-1
当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname, int flags, mode_t mode);
创建出来的文件权限为指定权限值&(~umask) //umask为文件权限掩码
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
read、write
ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数:fd 文件描述符
buf 存放位置
count 期望的个数
返回值:成功:实际读到的个数
返回-1:表示出错,并设置errno号
返回0:表示读到文件结尾
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd 文件描述符
buf 要写的内容
count 期望值
返回值:成功:实际写入数据的个数
失败 : -1
功能:从一个已打开的可读文件中读取数据
参数:fd 文件描述符
buf 存放位置
count 期望的个数
返回值:成功:实际读到的个数
返回-1:表示出错,并设置errno号
返回0:表示读到文件结尾
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd 文件描述符
buf 要写的内容
count 期望值
返回值:成功:实际写入数据的个数
失败 : -1
lseek
off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符
offset偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
返回值:成功:文件的当前位置
失败:-1
功能:设定文件的偏移位置
参数:fd:文件描述符
offset偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
返回值:成功:文件的当前位置
失败:-1
练习:2.实现“head -n 文件名”命令的功能:显示文件前n行
例:head -3 test.c -> ./a.out -3 test.c
atoi :将字符串转化成整型数 "1234" -- 1234 "-3"-- -3
3.用文件IO实现cp功能 ./a.out src dest
//读多少,写多少
例:head -3 test.c -> ./a.out -3 test.c
atoi :将字符串转化成整型数 "1234" -- 1234 "-3"-- -3
3.用文件IO实现cp功能 ./a.out src dest
//读多少,写多少
练习:3.用文件IO实现cp功能 ./a.out src dest
//读多少,写多少
//读多少,写多少
库
静态库
1.将源文件编译生成目标文件
gcc -c xxx.c -o xxx.o
2.创建静态库用ar命令
ar crs libxxx.a xxx.o
静态库命名规则:lib为库的前缀,xxx为库名,.a 为静态库的后缀(扩展名)
3.测试静态库的使用
gcc xxx.c -L指定库的路径 -l指定库名
执行./a.out
gcc -c xxx.c -o xxx.o
2.创建静态库用ar命令
ar crs libxxx.a xxx.o
静态库命名规则:lib为库的前缀,xxx为库名,.a 为静态库的后缀(扩展名)
3.测试静态库的使用
gcc xxx.c -L指定库的路径 -l指定库名
执行./a.out
动态库
1.用gcc创建动态库
gcc -fPIC -c xxx.c -o xxx.o
-fPIC 创建与地址无关的编译程序
gcc -shared -o libxxx.so xxx.o
动态库命名规则:lib为前缀,xxx为动态库名,.so为动态库的后缀(扩展名)
2.测动态库的使用
gcc xxx.c -L指定库的路径 -l指定库名
执行./a.out
gcc -fPIC -c xxx.c -o xxx.o
-fPIC 创建与地址无关的编译程序
gcc -shared -o libxxx.so xxx.o
动态库命名规则:lib为前缀,xxx为动态库名,.so为动态库的后缀(扩展名)
2.测动态库的使用
gcc xxx.c -L指定库的路径 -l指定库名
执行./a.out
三种方法解决动态库运行报错
(1)把库拷贝到/usr/lib和/lib目录下。
(2)在LD_LIBRARY_PATH环境变量中加上库所在路径。
(3) 添加/etc/ld.so.conf.d/*.conf文件。把库所在的路径加到文件末尾,并执行ldconfig刷新
进程
函数
fork
pid_t fork(void);
功能:创建子进程
返回值:
成功:在父进程中:返回子进程的进程号 >0
在子进程中:返回值为0
失败:-1并设置errno
功能:创建子进程
返回值:
成功:在父进程中:返回子进程的进程号 >0
在子进程中:返回值为0
失败:-1并设置errno
exit _exit
void exit(int status);
功能:结束进程,刷新缓存
参数:退出的状态
不返回。
void _exit(int status);
功能:结束进程,不刷新缓存
参数:status是一个整型的参数,可以利用这个参数传递进程结束时的状态。
通常0表示正常结束;
其他的数值表示出现了错误,进程非正常结束
功能:结束进程,刷新缓存
参数:退出的状态
不返回。
void _exit(int status);
功能:结束进程,不刷新缓存
参数:status是一个整型的参数,可以利用这个参数传递进程结束时的状态。
通常0表示正常结束;
其他的数值表示出现了错误,进程非正常结束
wait waitpid
pid_t wait(int *status);
功能:回收子进程资源(阻塞)
参数:status:子进程退出状态,不接受子进程状态设为NULL
返回值:成功:回收的子进程的进程号
失败:-1
pid_t waitpid(pid_t pid, int *status, int options);
功能:回收子进程资源
参数:
pid:>0 指定子进程进程号
=-1 任意子进程
=0 等待其组ID等于调用进程的组ID的任一子进程
<-1 等待其组ID等于pid的绝对值的任一子进程
status:子进程退出状态
options:0:阻塞
WNOHANG:非阻塞
返回值:正常:结束的子进程的进程号
当使用选项WNOHANG且没有子进程结束时:0
出错:-1
功能:回收子进程资源(阻塞)
参数:status:子进程退出状态,不接受子进程状态设为NULL
返回值:成功:回收的子进程的进程号
失败:-1
pid_t waitpid(pid_t pid, int *status, int options);
功能:回收子进程资源
参数:
pid:>0 指定子进程进程号
=-1 任意子进程
=0 等待其组ID等于调用进程的组ID的任一子进程
<-1 等待其组ID等于pid的绝对值的任一子进程
status:子进程退出状态
options:0:阻塞
WNOHANG:非阻塞
返回值:正常:结束的子进程的进程号
当使用选项WNOHANG且没有子进程结束时:0
出错:-1
getpid getppid
pid_t getpid(void);
功能:获取当前进程的进程号
pid_t getppid(void);
功能:获取当前进程的父进程号
功能:获取当前进程的进程号
pid_t getppid(void);
功能:获取当前进程的父进程号
1.exec函数族
2.守护进程
练习:创建一个守护进程,循环间隔1s向文件中写入一串字符“hello”
进程间通信方式
1.早期的进程间通信:
无名管道(pipe))
pipe
int pipe(int fd[2])
功能:创建无名管道
参数:文件描述符 fd[0]:读端 fd[1]:写端
返回值:成功 0
失败 -1
功能:创建无名管道
参数:文件描述符 fd[0]:读端 fd[1]:写端
返回值:成功 0
失败 -1
练习:父子进程实现通信,父进程循环从终端输入数据,子进程循环打印数据,当输入quit结束。
提示:管道自带同步机制。
提示:管道自带同步机制。
、有名管道(fifo
mkfifo
int mkfifo(const char *filename,mode_t mode);
功能:创健有名管道
参数:filename:有名管道文件名
mode:权限
返回值:成功:0
失败:-1,并设置errno号
注意对错误的处理方式:
如果错误是file exist时,注意加判断,如:if(errno == EEXIST)
功能:创健有名管道
参数:filename:有名管道文件名
mode:权限
返回值:成功:0
失败:-1,并设置errno号
注意对错误的处理方式:
如果错误是file exist时,注意加判断,如:if(errno == EEXIST)
练习:两个不相干进程,用有名管道实现cp (17分钟)
./input src
./output dest
./input src
./output dest
练习:两个不相干进程,用有名管道实现cp (17分钟)
./input src
./output dest
./input src
./output dest
信号(sem)
kill 、raise、pause
int kill(pid_t pid, int sig);
功能:信号发送
参数:pid:指定进程
sig:要发送的信号
返回值:成功 0
失败 -1
int raise(int sig);
功能:进程向自己发送信号
参数:sig:信号
返回值:成功 0
失败 -1
int pause(void);
功能:用于将调用进程挂起,直到捕捉到信号为止(返回)。
功能:信号发送
参数:pid:指定进程
sig:要发送的信号
返回值:成功 0
失败 -1
int raise(int sig);
功能:进程向自己发送信号
参数:sig:信号
返回值:成功 0
失败 -1
int pause(void);
功能:用于将调用进程挂起,直到捕捉到信号为止(返回)。
alarm
unsigned int alarm(unsigned int seconds)
功能:在进程中设置一个定时器
参数:seconds:定时时间,单位为秒
返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
注意:一个进程只能有一个闹钟时间。如果在调用alarm时
已设置过闹钟时间,则之前的闹钟时间被新值所代替
功能:在进程中设置一个定时器
参数:seconds:定时时间,单位为秒
返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
注意:一个进程只能有一个闹钟时间。如果在调用alarm时
已设置过闹钟时间,则之前的闹钟时间被新值所代替
signal
sighandler_t signal(int signum, sighandler_t handler);
功能:信号处理函数
参数:signum:要处理的信号
handler:信号处理方式
SIG_IGN:忽略信号
SIG_DFL:执行默认操作
handler:捕捉信号 void handler(int sig){} //函数名可以自定义
返回值:成功:设置之前的信号处理方式
失败:-1
功能:信号处理函数
参数:signum:要处理的信号
handler:信号处理方式
SIG_IGN:忽略信号
SIG_DFL:执行默认操作
handler:捕捉信号 void handler(int sig){} //函数名可以自定义
返回值:成功:设置之前的信号处理方式
失败:-1
练习:用信号的知识实现司机和售票员问题。
1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)
2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)
3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)
4)司机等待售票员下车,之后司机再下车。
1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)
2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)
3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)
4)司机等待售票员下车,之后司机再下车。
2.systerm V IPC(Inter-Process Communication")对象:
共享内存(share memory)
ftok
key_t ftok(const char *pathname, int proj_id);
功能:产生一个独一无二的key值
参数:
Pathname:已经存在的可访问文件的名字
Proj_id:一个字符(因为只用低8位)
返回值:成功:key值
失败:-1
功能:产生一个独一无二的key值
参数:
Pathname:已经存在的可访问文件的名字
Proj_id:一个字符(因为只用低8位)
返回值:成功:key值
失败:-1
shmget
int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开共享内存
参数:
key 键值
size 共享内存的大小
shmflg IPC_CREAT|IPC_EXCL(判错)|0666
返回值:成功 shmid
出错 -1(已编辑)
int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开共享内存
参数:
key 键值
size 共享内存的大小
shmflg IPC_CREAT|IPC_EXCL(判错)|0666
返回值:成功 shmid
出错 -1(已编辑)
shmat
void *shmat(int shmid,const void *shmaddr,int shmflg);
功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
参数:
shmid 共享内存的id号
shmaddr 一般为NULL,表示由系统自动完成映射
如果不为NULL,那么由用户指定
shmflg:SHM_RDONLY就是对该共享内存只进行读操作
0 可读可写
返回值:成功:完成映射后的地址,
失败:-1的地址
功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
参数:
shmid 共享内存的id号
shmaddr 一般为NULL,表示由系统自动完成映射
如果不为NULL,那么由用户指定
shmflg:SHM_RDONLY就是对该共享内存只进行读操作
0 可读可写
返回值:成功:完成映射后的地址,
失败:-1的地址
shmdt()
int shmdt(const void *shmaddr);
功能:取消映射
参数:要取消的地址
返回值:成功0
失败的-1
功能:取消映射
参数:要取消的地址
返回值:成功0
失败的-1
shmctl()
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
功能:(删除共享内存),对共享内存进行各种操作
参数:
shmid 共享内存的id号
cmd IPC_STAT 获得shmid属性信息,存放在第三参数
IPC_SET 设置shmid属性信息,要设置的属性放在第三参数
IPC_RMID:删除共享内存,此时第三个参数为NULL即可
返回:成功0
失败-1
用法:
shmctl(shmid,IPC_RMID,NULL);
功能:(删除共享内存),对共享内存进行各种操作
参数:
shmid 共享内存的id号
cmd IPC_STAT 获得shmid属性信息,存放在第三参数
IPC_SET 设置shmid属性信息,要设置的属性放在第三参数
IPC_RMID:删除共享内存,此时第三个参数为NULL即可
返回:成功0
失败-1
用法:
shmctl(shmid,IPC_RMID,NULL);
2.练习
两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束(19分钟)
共享内存
输入一次,打印一次。标志位
int char、
struct shm
{
int flag
char buf
}
struct shm * p = shmat();
两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束(19分钟)
共享内存
输入一次,打印一次。标志位
int char、
struct shm
{
int flag
char buf
}
struct shm * p = shmat();
消息队列(message queue)
msgget()
int msgget(key_t key, int flag);
功能:创建或打开一个消息队列
参数: key值
flag:创建消息队列的权限IPC_CREAT|IPC_EXCL|0666
返回值:成功:msgid
失败:-1
功能:创建或打开一个消息队列
参数: key值
flag:创建消息队列的权限IPC_CREAT|IPC_EXCL|0666
返回值:成功:msgid
失败:-1
msgsnd()
int msgsnd(int msqid, const void *msgp, size_t size, int flag);
功能:添加消息
参数:msqid:消息队列的ID
msgp:指向消息的指针。常用消息结构msgbuf如下:
struct msgbuf{
long mtype; //消息类型
char mtext[N]}; //消息正文
size:发送的消息正文的字节数
flag:IPC_NOWAIT消息没有发送完成函数也会立即返回
0:直到发送完成函数才返回
返回值:成功:0
失败:-1
功能:添加消息
参数:msqid:消息队列的ID
msgp:指向消息的指针。常用消息结构msgbuf如下:
struct msgbuf{
long mtype; //消息类型
char mtext[N]}; //消息正文
size:发送的消息正文的字节数
flag:IPC_NOWAIT消息没有发送完成函数也会立即返回
0:直到发送完成函数才返回
返回值:成功:0
失败:-1
msgrcv()
int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag);
功能:读取消息
参数:msgid:消息队列的ID
msgp:存放读取消息的空间
size:接受的消息正文的字节数
msgtype:0:接收消息队列中第一个消息。
大于0:接收消息队列中第一个类型为msgtyp的消息.
小于0:接收消息队列中类型值不小于msgtyp的绝对值且类型值又最小的消息。
flag:0:若无消息函数会一直阻塞
IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG
返回值:成功:接收到的消息的长度
失败:-1
功能:读取消息
参数:msgid:消息队列的ID
msgp:存放读取消息的空间
size:接受的消息正文的字节数
msgtype:0:接收消息队列中第一个消息。
大于0:接收消息队列中第一个类型为msgtyp的消息.
小于0:接收消息队列中类型值不小于msgtyp的绝对值且类型值又最小的消息。
flag:0:若无消息函数会一直阻塞
IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG
返回值:成功:接收到的消息的长度
失败:-1
msgctl()
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
功能:对消息队列的操作,删除消息队列
参数:msqid:消息队列的队列ID
cmd:
IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区中。
IPC_SET:设置消息队列的属性。这个值取自buf参数。
IPC_RMID:从系统中删除消息队列。
buf:消息队列缓冲区
返回值:成功:0
失败:-1
功能:对消息队列的操作,删除消息队列
参数:msqid:消息队列的队列ID
cmd:
IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区中。
IPC_SET:设置消息队列的属性。这个值取自buf参数。
IPC_RMID:从系统中删除消息队列。
buf:消息队列缓冲区
返回值:成功:0
失败:-1
信号灯集(semaphore)
semget()
int semget(key_t key, int nsems, int semflg);
功能:创建/打开信号灯
参数:key:ftok产生的key值
nsems:信号灯集中包含的信号灯数目
semflg:信号灯集的访问权限,通常为IPC_CREAT |IPC_EXCL |0666
返回值:成功:信号灯集ID
失败:-1
功能:创建/打开信号灯
参数:key:ftok产生的key值
nsems:信号灯集中包含的信号灯数目
semflg:信号灯集的访问权限,通常为IPC_CREAT |IPC_EXCL |0666
返回值:成功:信号灯集ID
失败:-1
semctl()
int semctl ( int semid, int semnum, int cmd…/*union semun arg*/);
功能:信号灯集合的控制(初始化/删除)
参数:semid:信号灯集ID
semnum: 要操作的集合中的信号灯编号
cmd:
GETVAL:获取信号灯的值,返回值是获得值
SETVAL:设置信号灯的值,需要用到第四个参数:共用体
IPC_RMID:从系统中删除信号灯集合
返回值:成功 0
失败 -1
用法:初始化:
union semun{
int val;
}mysemun;
mysemun.val = 10;
semctl(semid, 0, SETVAL, mysemun);
获取信号灯值:函数semctl(semid, 0, GETVAL)的返回值
删除信号灯集:semctl(semid, 0, IPC_RMID);
功能:信号灯集合的控制(初始化/删除)
参数:semid:信号灯集ID
semnum: 要操作的集合中的信号灯编号
cmd:
GETVAL:获取信号灯的值,返回值是获得值
SETVAL:设置信号灯的值,需要用到第四个参数:共用体
IPC_RMID:从系统中删除信号灯集合
返回值:成功 0
失败 -1
用法:初始化:
union semun{
int val;
}mysemun;
mysemun.val = 10;
semctl(semid, 0, SETVAL, mysemun);
获取信号灯值:函数semctl(semid, 0, GETVAL)的返回值
删除信号灯集:semctl(semid, 0, IPC_RMID);
semop
int semop ( int semid, struct sembuf *opsptr, size_t nops);
功能:对信号灯集合中的信号量进行PV操作
参数:semid:信号灯集ID
opsptr:操作方式
nops: 要操作的信号灯的个数 1个
返回值:成功 :0
失败:-1
struct sembuf {
short sem_num; // 要操作的信号灯的编号
short sem_op; // 0 : 等待,直到信号灯的值变成0
// 1 : 释放资源,V操作
// -1 : 申请资源,P操作
short sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
};
用法:
申请资源 P操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = -1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
释放资源 V操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = 1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
功能:对信号灯集合中的信号量进行PV操作
参数:semid:信号灯集ID
opsptr:操作方式
nops: 要操作的信号灯的个数 1个
返回值:成功 :0
失败:-1
struct sembuf {
short sem_num; // 要操作的信号灯的编号
short sem_op; // 0 : 等待,直到信号灯的值变成0
// 1 : 释放资源,V操作
// -1 : 申请资源,P操作
short sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
};
用法:
申请资源 P操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = -1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
释放资源 V操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = 1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
5.练习
共享内存+信号灯集实现,两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束(20分钟)
共享内存+信号灯集实现,两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束(20分钟)
3.BSD:
套接字(socket)
2.练习:
通过父子进程完成对文件的拷贝(cp),父进程从文件开始到文件的一半开始拷贝,子进程从文件的一半到文件末尾。要求:文件IO cp src dest
提示:1)文件一半lseek
2)最后一次读剩下的1000-32-32 18
3)fork之前打开文件?还是之后?
通过父子进程完成对文件的拷贝(cp),父进程从文件开始到文件的一半开始拷贝,子进程从文件的一半到文件末尾。要求:文件IO cp src dest
提示:1)文件一半lseek
2)最后一次读剩下的1000-32-32 18
3)fork之前打开文件?还是之后?
练习:题目要求:编程读写一个文件test.txt,每隔1秒向文件中写入一行数据,类似这样:
1, 2007-7-30 15:16:42
2, 2007-7-30 15:16:43
该程序应该无限循环,直到按Ctrl+C中断程序。
再次启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号,比如:
1, 2007-7-30 15:16:42
2, 2007-7-30 15:16:43
3, 2007-7-30 15:19:02
4, 2007-7-30 15:19:03
5, 2007-7-30 15:19:04
提示:1.sleep(1)
2.fopen a+
3.计算行号
4.时间:
//time:获取从1970年1月1日0时0分0秒到现在的秒数
//localtime:将时间秒数转化成结构体
//sprintf ->sprintf(buf,"%d-%d",year,month);
//fprintf ->fprintf(fp,"%d-%d",year,month);//缓冲区?
1, 2007-7-30 15:16:42
2, 2007-7-30 15:16:43
该程序应该无限循环,直到按Ctrl+C中断程序。
再次启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号,比如:
1, 2007-7-30 15:16:42
2, 2007-7-30 15:16:43
3, 2007-7-30 15:19:02
4, 2007-7-30 15:19:03
5, 2007-7-30 15:19:04
提示:1.sleep(1)
2.fopen a+
3.计算行号
4.时间:
//time:获取从1970年1月1日0时0分0秒到现在的秒数
//localtime:将时间秒数转化成结构体
//sprintf ->sprintf(buf,"%d-%d",year,month);
//fprintf ->fprintf(fp,"%d-%d",year,month);//缓冲区?
标准IO
BCD-LSP
函数
fopen 、fclose
fgetc、fputc
fgets、fputs
char * fgets(char *s, int size, FILE * stream);
功能:从文件中每次读取一行字符串
参数:s:存放字符串的地址
size:一次读取的字符个数
stream:文件流
返回值:成功:s的地址
失败或读到文件末尾:NULL
特性:每次实际读取的字符个数为size-1个,会在末尾自动添加\0
每次读一行,遇到\n后不再继续,读下一行
int fputs(const char *s, FILE * stream);
功能:向文件中写字符串
参数:s:要写的内容
stream:文件流
返回值:成功:非负整数
失败:EOF
功能:从文件中每次读取一行字符串
参数:s:存放字符串的地址
size:一次读取的字符个数
stream:文件流
返回值:成功:s的地址
失败或读到文件末尾:NULL
特性:每次实际读取的字符个数为size-1个,会在末尾自动添加\0
每次读一行,遇到\n后不再继续,读下一行
int fputs(const char *s, FILE * stream);
功能:向文件中写字符串
参数:s:要写的内容
stream:文件流
返回值:成功:非负整数
失败:EOF
freopen fseek ftell rewind
FILE * freopen(const char *pathname, const char *mode, FILE* fp)
功能:将指定的文件流重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同fopen)
fp:文件流指针
返回值:成功:返回文件流指针
失败:NULL
功能:将指定的文件流重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同fopen)
fp:文件流指针
返回值:成功:返回文件流指针
失败:NULL
feof、ferror
fread、fwrite
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件流读取多个元素
参数: ptr :用来存放读取元素
size :元素大小 sizeof(数据类型)
nmemb :读取元素的个数
stream :要读取的文件
返回值:成功:读取的元素的个数;
读到文件尾: 0
失败: -1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:按对象写
参数:同上
返回值:成功:写的元素个数
失败 :-1
功能:从文件流读取多个元素
参数: ptr :用来存放读取元素
size :元素大小 sizeof(数据类型)
nmemb :读取元素的个数
stream :要读取的文件
返回值:成功:读取的元素的个数;
读到文件尾: 0
失败: -1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:按对象写
参数:同上
返回值:成功:写的元素个数
失败 :-1
练习: 用fgetc fputc实现cat 文件名功能。--》./a.out 文件名( 17分钟)
2.练习:通过fgets实现"wc -l 文件名"命令功能(计算文件行数)
char buf[32]
//每一行一定小于32?
char buf[32]
//每一行一定小于32?
练习 :用标准IO实现(cp 源文件 目标文件)功能
练习:2.实现“head -n 文件名”命令的功能:显示文件前n行
例:head -3 test.c -> ./a.out -3 test.c
atoi :将字符串转化成整型数 "1234" -- 1234 "-3"-- -3
例:head -3 test.c -> ./a.out -3 test.c
atoi :将字符串转化成整型数 "1234" -- 1234 "-3"-- -3
目录操作
opendir closedir
DIR *opendir(const char *name);
功能:获得目录流
参数:要打开的目录
返回值:成功:目录流
失败:NULL
int closedir(DIR *dirp);
功能:关闭目录
参数:dirp:目录流
功能:获得目录流
参数:要打开的目录
返回值:成功:目录流
失败:NULL
int closedir(DIR *dirp);
功能:关闭目录
参数:dirp:目录流
readdir
directory entry
struct dirent *readdir(DIR *dirp);
功能:读目录
参数:要读的目录流
返回值:成功:读到的信息
失败:NULL,设置errno号
返回值为结构体,该结构体成员为描述该目录下的文件信息
struct dirent {
ino_t d_ino; /* 索引节点号*/
off_t d_off; /*在目录文件中的偏移*/
unsigned short d_reclen; /* 文件名长度*/
unsigned char d_type; /* 文件类型 */
char d_name[256]; /* 文件名 */
};
struct dirent *readdir(DIR *dirp);
功能:读目录
参数:要读的目录流
返回值:成功:读到的信息
失败:NULL,设置errno号
返回值为结构体,该结构体成员为描述该目录下的文件信息
struct dirent {
ino_t d_ino; /* 索引节点号*/
off_t d_off; /*在目录文件中的偏移*/
unsigned short d_reclen; /* 文件名长度*/
unsigned char d_type; /* 文件类型 */
char d_name[256]; /* 文件名 */
};
练习:实现ls
获取文件属性
state
int stat(const char *path, struct stat *buf);
功能:获取文件属性
参数:path:文件路径名
buf:保存文件属性信息的结构体
返回值:成功:0
失败:-1
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 */
off_t st_size; /* 大小 */
dev_t st_rdev; /* 设备ID */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};
功能:获取文件属性
参数:path:文件路径名
buf:保存文件属性信息的结构体
返回值:成功:0
失败:-1
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 */
off_t st_size; /* 大小 */
dev_t st_rdev; /* 设备ID */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};
getgrgid
struct group *getgrgid(gid_t gid);
功能:通过组 id 获取组属性
参数:gid:组 id
返回值:返回保存组相关属性结构体的地址 err:NULL
struct group {
char *gr_name; /* 组名 */
char *gr_passwd; /* 组密码 */
gid_t gr_gid; /* 组ID */
char **gr_mem; /*组成员账号 */
};
功能:通过组 id 获取组属性
参数:gid:组 id
返回值:返回保存组相关属性结构体的地址 err:NULL
struct group {
char *gr_name; /* 组名 */
char *gr_passwd; /* 组密码 */
gid_t gr_gid; /* 组ID */
char **gr_mem; /*组成员账号 */
};
getpwuid()
struct passwd *getpwuid(uid_t uid);
功能:通过用户 id 获取用户属性
参数:uid:用户 id
返回值:返回保存用户相关属性结构体的地址
失败:NULL
struct passwd {
char *pw_name; /* 用户名 */
char *pw_passwd; /* 密码 */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* 真实名 */
char *pw_dir; /* 主目录 */
char *pw_shell; /* 使用的shell */
};
功能:通过用户 id 获取用户属性
参数:uid:用户 id
返回值:返回保存用户相关属性结构体的地址
失败:NULL
struct passwd {
char *pw_name; /* 用户名 */
char *pw_passwd; /* 密码 */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* 真实名 */
char *pw_dir; /* 主目录 */
char *pw_shell; /* 使用的shell */
};
ctime
char *ctime(const time_t *timep);
功能:将时间秒数转化为字符串表示
参数:timep :时间
返回值:成功返回字符串首地址
失败:NULL
功能:将时间秒数转化为字符串表示
参数:timep :时间
返回值:成功返回字符串首地址
失败:NULL
线程
函数
pthread_create pthread_exit
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
功能:创建线程
参数:thread:线程标识
attr:线程属性, NULL:代表设置默认属性
start_routine:函数名:代表线程函数
arg:用来给前面函数传参
返回值:成功:0
失败:错误码
int pthread_exit(void *value_ptr)
功能:用于退出线程的执行
参数:value_ptr:线程退出时返回的值(任意类型)
返回值:成功 : 0
失败:errno
void *(*start_routine) (void *), void *arg);
功能:创建线程
参数:thread:线程标识
attr:线程属性, NULL:代表设置默认属性
start_routine:函数名:代表线程函数
arg:用来给前面函数传参
返回值:成功:0
失败:错误码
int pthread_exit(void *value_ptr)
功能:用于退出线程的执行
参数:value_ptr:线程退出时返回的值(任意类型)
返回值:成功 : 0
失败:errno
pthread_join pthread_detach
int pthread_join(pthread_t thread, void **value_ptr)
功能:用于等待一个指定的线程结束,阻塞函数
参数:thread:创建的线程对象
value_ptr:指针*value_ptr指向线程返回的参数
返回值:成功 : 0
失败:errno
int pthread_detach(pthread_t thread);
功能:让线程结束时自动回收线程资源,让线程和主线程分离
参数:thread:线程ID
功能:用于等待一个指定的线程结束,阻塞函数
参数:thread:创建的线程对象
value_ptr:指针*value_ptr指向线程返回的参数
返回值:成功 : 0
失败:errno
int pthread_detach(pthread_t thread);
功能:让线程结束时自动回收线程资源,让线程和主线程分离
参数:thread:线程ID
练习:
通过线程实现数据的交互,主线程循环从终端输入,线程函数将数据循环输出,当输入quit结束程序。(13分钟)
提示:1)全局变量
2)输入一次,打印一次--》同步--》标志位
标志位:int flag可输出(输入完成)/不可输出状态(打印完成)
通过线程实现数据的交互,主线程循环从终端输入,线程函数将数据循环输出,当输入quit结束程序。(13分钟)
提示:1)全局变量
2)输入一次,打印一次--》同步--》标志位
标志位:int flag可输出(输入完成)/不可输出状态(打印完成)
同步,信号量实现
sem_init()
int sem_init(sem_t *sem, int pshared, unsigned int value)
功能:初始化信号量
参数:sem:初始化的信号量对象
pshared:信号量共享的范围(0: 线程间使用 非0:1进程间使用)
value:信号量初值
返回值:成功 0
失败 -1
功能:初始化信号量
参数:sem:初始化的信号量对象
pshared:信号量共享的范围(0: 线程间使用 非0:1进程间使用)
value:信号量初值
返回值:成功 0
失败 -1
sem_wait()
int sem_wait(sem_t *sem)
功能:申请资源 P操作
参数:sem:信号量对象
返回值:成功 0
失败 -1
功能:申请资源 P操作
参数:sem:信号量对象
返回值:成功 0
失败 -1
sem_post()
int sem_post(sem_t *sem)
功能:释放资源 V操作
参数:sem:信号量对象
返回值:成功 0
失败 -1
注:释放一次信号量的值加1,函数不阻塞
功能:释放资源 V操作
参数:sem:信号量对象
返回值:成功 0
失败 -1
注:释放一次信号量的值加1,函数不阻塞
练习:通过线程实现数据的交互,主线程循环从终端输入,线程函数将数据循环输出,当输入quit结束程序。输入一次,打印一次
互斥和条件变量
互斥的函数
pthread_mutex_init()
pthread_mutex_destroy()
pthread_mutex_destroy()
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
功能:初始化互斥锁
参数:mutex:互斥锁
attr: 互斥锁属性 // NULL表示缺省属性
返回值:成功 0
失败 -1
int pthread_mutex_destroy(pthread_mutex_t *mutex)
功能:销毁互斥锁
参数:mutex:互斥锁
功能:初始化互斥锁
参数:mutex:互斥锁
attr: 互斥锁属性 // NULL表示缺省属性
返回值:成功 0
失败 -1
int pthread_mutex_destroy(pthread_mutex_t *mutex)
功能:销毁互斥锁
参数:mutex:互斥锁
pthread_mutex_lock()
pthread_mutex_unlock()
pthread_mutex_unlock()
int pthread_mutex_lock(pthread_mutex_t *mutex)
功能:申请互斥锁
参数:mutex:互斥锁
返回值:成功 0
失败 -1
注:和pthread_mutex_trylock区别:pthread_mutex_lock是阻塞的;pthread_mutex_trylock不阻塞,如果申请不到锁会立刻返回
int pthread_mutex_unlock(pthread_mutex_t *mutex)
功能:释放互斥锁
参数:mutex:互斥锁
返回值:成功 0
失败 -1
功能:申请互斥锁
参数:mutex:互斥锁
返回值:成功 0
失败 -1
注:和pthread_mutex_trylock区别:pthread_mutex_lock是阻塞的;pthread_mutex_trylock不阻塞,如果申请不到锁会立刻返回
int pthread_mutex_unlock(pthread_mutex_t *mutex)
功能:释放互斥锁
参数:mutex:互斥锁
返回值:成功 0
失败 -1
条件变量的函数
pthread_cond_init()
pthread_cond_destroy()
pthread_cond_destroy()
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
功能:初始化条件变量
参数:cond:是一个指向结构pthread_cond_t的指针
restrict attr:是一个指向结构pthread_condattr_t的指针,一般设为NULL
返回值:成功:0 失败:非0
注:必须等待pthread_cond_wait函数先执行,再产生条件才可以
int pthread_cond_destroy(pthread_cond_t *cond);
功能:将条件变量销毁
参数:cond:条件变量值
返回值:成功:0, 失败:非0
功能:初始化条件变量
参数:cond:是一个指向结构pthread_cond_t的指针
restrict attr:是一个指向结构pthread_condattr_t的指针,一般设为NULL
返回值:成功:0 失败:非0
注:必须等待pthread_cond_wait函数先执行,再产生条件才可以
int pthread_cond_destroy(pthread_cond_t *cond);
功能:将条件变量销毁
参数:cond:条件变量值
返回值:成功:0, 失败:非0
pthread_cond_wait()
pthread_cond_signal()
pthread_cond_signal()
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
功能:等待信号的产生
参数:restrict cond:要等待的条件
restrict mutex:对应的锁
返回值:成功:0,失败:不为0
注:当没有条件产生时函数会阻塞,同时会将锁解开;如果等待到条件产生,函数会结束阻塞同时进行上锁。
int pthread_cond_signal(pthread_cond_t *cond);
功能:给条件变量发送信号
参数:cond:条件变量值
返回值:成功:0,失败:非0
功能:等待信号的产生
参数:restrict cond:要等待的条件
restrict mutex:对应的锁
返回值:成功:0,失败:不为0
注:当没有条件产生时函数会阻塞,同时会将锁解开;如果等待到条件产生,函数会结束阻塞同时进行上锁。
int pthread_cond_signal(pthread_cond_t *cond);
功能:给条件变量发送信号
参数:cond:条件变量值
返回值:成功:0,失败:非0
3.练习:
两个线程:一个线程循环倒置,一个线程循环打印
int a[10]={0,1,2,3,4,5,6,7,8,9}
锁谁-》临界区
上锁(申请)--》倒置--》解锁(释放)
上锁(申请)--》打印--》解锁(释放)
两个线程:一个线程循环倒置,一个线程循环打印
int a[10]={0,1,2,3,4,5,6,7,8,9}
锁谁-》临界区
上锁(申请)--》倒置--》解锁(释放)
上锁(申请)--》打印--》解锁(释放)
0 条评论
下一页