高级I\O
非阻塞IO – 阻塞 IO
补充:有限状态机编程
有限状态机
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1,
STATE_W,
/*异常终止态*/
STATE_Ex,
STATE_T
};
struct fsm_st
{
int state;
int sfd;
int dfd;
int len;
int pos;
char * errstr;
char buf[BUFSIZE];
};
static void fsm_driver(struct fsm_st*fsm)
{
int ret;
switch (fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if (fsm->len == 0)
fsm->state = STATE_T;
else if (fsm->len < 0)
{
if (errno == EAGAIN)
fsm->state =STATE_R;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state =STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if (errno == EAGAIN)
fsm->state =STATE_W;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos += ret;
fsm->len -= ret;
if(fsm->len == 0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}
break;
case STATE_Ex:
perror(fsm->errstr);
fsm->state = STATE_T;
break;
case STATE_T:
/*do sth*/
break;
default:
/*发送异常*/
abort();
break;
}
}
static void relay(int fd1,int fd2)
{
int fd1_save,fd2_save;
struct fsm_st fsm12,fsm21;
/*保证两个文件是以非阻塞方式实现*/
fd1_save = fcntl(fd1,F_GETFL);
fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);
fd2_save = fcntl(fd2,F_GETFL);
fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);
fsm12.state = STATE_R;
fsm12.sfd = fd1;
fsm12.dfd = fd2;
fsm21.state = STATE_R;
fsm21.sfd = fd2;
fsm21.dfd = fd1;
while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
{
fsm_driver(&fsm12);
fsm_driver(&fsm21);
}
/*恢复之前的状态*/
fcntl(fd1,F_SETFL,fd1_save);
fcntl(fd2,F_SETFL,fd2_save);
}
int main()
{
int fd1,fd2;
fd1 = open(TTY1,O_RDWR);
if (fd1<0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
if (fd2<0)
{
perror("open()");
exit(1);
}
write(fd2,"TTY2\n",5);
relay(fd1,fd2);
close(fd2);
close(fd1);
exit(0);
}
简单流程:自然流程是结构化的
复杂流程:自然流程不是结构化的
1、非阻塞IO
中继引擎实现实例
.h文件
#ifndef RELAYER_H__
#define RELAYER_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define REL_JOBMAX 10000
enum
{
STATE_RUNNING=1,
STATE_CANCELED,
STATE_OVER
};
struct rel_stat_st
{
int state;
int fd1;
int fd2;
int64_t count12,count21;
//struct timerval start end;
};
int rel_addjob(int fd,int fd2);
/*
* return >=0 成功 返回当前任务ID
* == -EINVAL 失败 参数非法
* == -ENOSPC 失败 任务数组满
* == -ENNMEM 失败 内存分配有误
*
*/
int rel_canceljob(int fd);
/*
* return == 0 成功 制定任务成功取消
* == -EINVAL 失败 参数非法
* == -EBUSY 失败 任务早已被取消
*/
int rel_waitjob(int fd,struct rel_stat_st *);
/*
* return == 0 成功 指定任务已终止并返回状态
* == -EINVAL 失败 参数非法
* == -EBUSY 失败 任务早已被取消
*/
int rel_statjob(int fd,struct rel_stat_st *);
/*
* return == 0 成功 指定状态已经返回
* == -EINVAL 失败 参数非法
* == -EBUSY 失败 任务早已被取消
*/
#endif // !RELAYER_H__
relayer.c文件
#include "relayer.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1,
STATE_W,
/*异常终止态*/
STATE_Ex,
STATE_T
};
struct rel_fsm_st
{
int state;
int sfd;
int dfd;
int len;
int pos;
char * errstr;
char buf[BUFSIZE];
int64_t count;
};
struct rel_job_st
{
int job_state;
int fd1;
int fd2;
struct rel_fsm_st fsm12,fsm21;
int fd1_save,fd2_save;
};
static struct rel_job_st* rel_job[REL_JOBMAX];
static pthread_mutex_t mut_rel_job = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
static void fsm_driver(struct rel_fsm_st*fsm)
{
int ret;
switch (fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if (fsm->len == 0)
fsm->state = STATE_T;
else if (fsm->len < 0)
{
if (errno == EAGAIN)
fsm->state =STATE_R;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state =STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if (errno == EAGAIN)
fsm->state =STATE_W;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos += ret;
fsm->len -= ret;
if(fsm->len == 0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}
break;
case STATE_Ex:
perror(fsm->errstr);
fsm->state = STATE_T;
break;
case STATE_T:
/*do sth*/
break;
default:
/*发送异常*/
abort();
break;
}
}
static void *thr_relayer(void *p)
{
while (1)
{
pthread_mutex_lock(&mut_rel_job);
for (int i = 0; i < REL_JOBMAX; i++)
{
if (rel_job[i]!=NULL)
{
if (rel_job[i]->job_state == STATE_RUNNING)
{
fsm_driver(&rel_job[i]->fsm12);
fsm_driver(&rel_job[i]->fsm21);
if(rel_job[i]->fsm12.state == STATE_T&&rel_job[i]->fsm21.state == STATE_T)
{
rel_job[i]->job_state = STATE_OVER;
}
}
}
}
pthread_mutex_unlock(&mut_rel_job);
}
}
//static module_unload(void)
static void module_load(void)
{
int err = 0;
pthread_t tid_relayer;
err = pthread_create(&tid_relayer,NULL,thr_relayer,NULL);
if (err)
{
fprintf(stderr,"pthread_create():%s\n",strerror(err));
exit(1);
}
}
static int get_free_pos_unlocked()
{
int i;
for (i = 0; i < REL_JOBMAX; i++)
{
if (rel_job[i]==NULL)
return i;
}
return -1;
}
int rel_addjob(int fd1,int fd2)
{
struct rel_job_st *me;
/*动态模块的一次性初始化*/
pthread_once(&init_once,module_load);
int pos = 0;
me = malloc(sizeof(*me));
if (me == NULL)
return -ENOMEM;
me->fd1 = fd1;
me->fd2 = fd2;
me->job_state = STATE_RUNNING;
/*保存状态,确保fd1和fd2都是非阻塞打开的*/
me->fd1_save = fcntl(me->fd1,F_GETFL);
fcntl(me->fd1,F_SETFL,me->fd1_save|O_NONBLOCK);
me->fd2_save = fcntl(me->fd2,F_GETFL);
fcntl(me->fd2,F_SETFL,me->fd2_save|O_NONBLOCK);
me->fsm12.sfd = me->fd1;
me->fsm12.dfd = me->fd2;
me->fsm12.state = STATE_R;
me->fsm21.sfd = me->fd2;
me->fsm21.dfd = me->fd1;
me->fsm21.state = STATE_R;
pthread_mutex_lock(&mut_rel_job);
get_free_pos_unlocked();
if (pos < 0)
{
pthread_mutex_unlock(&mut_rel_job);
fcntl(me->fd1,F_SETFL,me->fd1_save);
fcntl(me->fd2,F_SETFL,me->fd2_save);
free(me);
return -ENOSPC;
}
rel_job[pos] = me;
pthread_mutex_unlock(&mut_rel_job);
return pos;
}
#if 0
int re_canceljob(int fd);
int re_waitjob(int fd,struct rel_stat_st *);
int re_statjob(int fd,struct rel_stat_st *);
#endif
main.c文件
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "relayer.h"
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define TTY3 "/dev/tty10"
#define TTY4 "/dev/tty9"
int main()
{
int fd1,fd2,fd3,fd4;
int job1,job2;
fd1 = open(TTY1,O_RDWR);
if (fd1<0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
if (fd2<0)
{
perror("open()");
exit(1);
}
write(fd2,"TTY2\n",5);
job1 = rel_addjob(fd1,fd2);
if (job1 < 0)
{
fprintf(stderr,"rel_addjob():%s\n",strerror(-job1));
exit(1);
}
fd3 = open(TTY3,O_RDWR);
if (fd3<0)
{
perror("open()");
exit(1);
}
write(fd3,"TTY3\n",5);
fd4 = open(TTY4,O_RDWR);
if (fd4<0)
{
perror("open()");
exit(1);
}
write(fd3,"TTY4\n",5);
job2 = rel_addjob(fd3,fd4);
if (job2<0)
{
fprintf(stderr,"rel_addjob():%s\n",strerror(-job2));
exit(1);
}
while (1)
pause();
close(fd2);
close(fd1);
close(fd3);
close(fd4);
exit(0);
}
2、IO多路转接
select();//移植性非常好,以事件为单位组织文件描述符。
select()示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1,
STATE_W,
/*异常终止态*/
STATE_AUTO,
STATE_Ex,
STATE_T
};
struct fsm_st
{
int state;
int sfd;
int dfd;
int len;
int pos;
char * errstr;
char buf[BUFSIZE];
};
static void fsm_driver(struct fsm_st*fsm)
{
int ret;
switch (fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if (fsm->len == 0)
fsm->state = STATE_T;
else if (fsm->len < 0)
{
if (errno == EAGAIN)
fsm->state =STATE_R;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state =STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if (errno == EAGAIN)
fsm->state =STATE_W;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos += ret;
fsm->len -= ret;
if(fsm->len == 0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}
break;
case STATE_Ex:
perror(fsm->errstr);
fsm->state = STATE_T;
break;
case STATE_T:
/*do sth*/
break;
default:
/*发送异常*/
abort();
break;
}
}
static int max(int a,int b)
{
if (a>b)
return a;
return b;
}
static void relay(int fd1,int fd2)
{
int fd1_save,fd2_save;
struct fsm_st fsm12,fsm21;
fd_set rset,wset;
/*保证两个文件是以非阻塞方式实现*/
fd1_save = fcntl(fd1,F_GETFL);
fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);
fd2_save = fcntl(fd2,F_GETFL);
fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);
fsm12.state = STATE_R;
fsm12.sfd = fd1;
fsm12.dfd = fd2;
fsm21.state = STATE_R;
fsm21.sfd = fd2;
fsm21.dfd = fd1;
while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
{
//布置监视任务
//读集设置为空集
FD_ZERO(&rset);
FD_ZERO(&wset);
if (fsm12.state == STATE_R)
FD_SET(fsm12.sfd,&rset);
if (fsm12.state == STATE_W)
FD_SET(fsm12.sfd,&wset);
if (fsm21.state == STATE_R)
FD_SET(fsm21.sfd,&rset);
if (fsm21.state == STATE_W)
FD_SET(fsm21.sfd,&wset);
//监视
if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
{
if (select(max(fd1,fd2)+1,&rset,&wset,NULL,NULL)<0)
{
if (errno == EINTR)
continue;
perror("select()");
exit(1);
}
}
//查看监视结果
if(FD_ISSET(fd1,&rset)||FD_ISSET(fd2,&wset)||fsm12.state > STATE_AUTO)
fsm_driver(&fsm12);
if(FD_ISSET(fd2,&rset)||FD_ISSET(fd1,&wset)||fsm12.state > STATE_AUTO)
fsm_driver(&fsm21);
}
/*恢复之前的状态*/
fcntl(fd1,F_SETFL,fd1_save);
fcntl(fd2,F_SETFL,fd2_save);
}
int main()
{
int fd1,fd2;
fd1 = open(TTY1,O_RDWR);
if (fd1<0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
if (fd2<0)
{
perror("open()");
exit(1);
}
write(fd2,"TTY2\n",5);
relay(fd1,fd2);
close(fd2);
close(fd1);
exit(0);
}
poll();//以文件描述符为单位来组织事件,也可以移植。
poll示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1,
STATE_W,
/*异常终止态*/
STATE_AUTO,
STATE_Ex,
STATE_T
};
struct fsm_st
{
int state;
int sfd;
int dfd;
int len;
int pos;
char * errstr;
char buf[BUFSIZE];
};
static void fsm_driver(struct fsm_st*fsm)
{
int ret;
switch (fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if (fsm->len == 0)
fsm->state = STATE_T;
else if (fsm->len < 0)
{
if (errno == EAGAIN)
fsm->state =STATE_R;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state =STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if (errno == EAGAIN)
fsm->state =STATE_W;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos += ret;
fsm->len -= ret;
if(fsm->len == 0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}
break;
case STATE_Ex:
perror(fsm->errstr);
fsm->state = STATE_T;
break;
case STATE_T:
/*do sth*/
break;
default:
/*发送异常*/
abort();
break;
}
}
static int max(int a,int b)
{
if (a>b)
return a;
return b;
}
static void relay(int fd1,int fd2)
{
int fd1_save,fd2_save;
struct fsm_st fsm12,fsm21;
struct pollfd pfd[2];
/*保证两个文件是以非阻塞方式实现*/
fd1_save = fcntl(fd1,F_GETFL);
fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);
fd2_save = fcntl(fd2,F_GETFL);
fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);
fsm12.state = STATE_R;
fsm12.sfd = fd1;
fsm12.dfd = fd2;
fsm21.state = STATE_R;
fsm21.sfd = fd2;
fsm21.dfd = fd1;
pfd[0].fd = fd1;
pfd[1].fd = fd2;
while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
{
//布置监视任务
//读集设置为空集
pfd[0].events = 0;
if (fsm12.state == STATE_R)
pfd[0].events |= POLLIN;
if (fsm21.state == STATE_W)
pfd[0].events |= POLLOUT;
pfd[1].events = 0;
if (fsm21.state == STATE_R)
pfd[1].events |= POLLIN;
if (fsm12.state == STATE_W)
pfd[1].events |= POLLOUT;
//监视
if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
{
while(poll(pfd,2,-1)<0)
{
if (errno == EINTR)
continue;
perror("poll()");
exit(1);
}
}
//查看监视结果
if(pfd[0].revents&POLLIN|| pfd[1].revents&POLLOUT||fsm12.state > STATE_AUTO)
fsm_driver(&fsm12);
if(pfd[1].revents&POLLIN|| pfd[0].revents&POLLOUT||fsm12.state > STATE_AUTO)
fsm_driver(&fsm21);
}
/*恢复之前的状态*/
fcntl(fd1,F_SETFL,fd1_save);
fcntl(fd2,F_SETFL,fd2_save);
}
int main()
{
int fd1,fd2;
fd1 = open(TTY1,O_RDWR);
if (fd1<0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
if (fd2<0)
{
perror("open()");
exit(1);
}
write(fd2,"TTY2\n",5);
relay(fd1,fd2);
close(fd2);
close(fd1);
exit(0);
}
epoll();//linux的方言,无法移植。
epoll示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1,
STATE_W,
/*异常终止态*/
STATE_AUTO,
STATE_Ex,
STATE_T
};
struct fsm_st
{
int state;
int sfd;
int dfd;
int len;
int pos;
char * errstr;
char buf[BUFSIZE];
};
static void fsm_driver(struct fsm_st*fsm)
{
int ret;
switch (fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if (fsm->len == 0)
fsm->state = STATE_T;
else if (fsm->len < 0)
{
if (errno == EAGAIN)
fsm->state =STATE_R;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state =STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if (errno == EAGAIN)
fsm->state =STATE_W;
else
{
fsm->errstr = "read()";
fsm->state =STATE_Ex;
}
}
else
{
fsm->pos += ret;
fsm->len -= ret;
if(fsm->len == 0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}
break;
case STATE_Ex:
perror(fsm->errstr);
fsm->state = STATE_T;
break;
case STATE_T:
/*do sth*/
break;
default:
/*发送异常*/
abort();
break;
}
}
static int max(int a,int b)
{
if (a>b)
return a;
return b;
}
static void relay(int fd1,int fd2)
{
int fd1_save,fd2_save;
struct fsm_st fsm12,fsm21;
struct epoll_event ev;
int epfd;
/*保证两个文件是以非阻塞方式实现*/
fd1_save = fcntl(fd1,F_GETFL);
fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);
fd2_save = fcntl(fd2,F_GETFL);
fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);
fsm12.state = STATE_R;
fsm12.sfd = fd1;
fsm12.dfd = fd2;
fsm21.state = STATE_R;
fsm21.sfd = fd2;
fsm21.dfd = fd1;
epfd = epoll_create(10);
if (epfd < 0 )
{
perror("epoll_create()");
exit(1);
}
ev.events = 0;
ev.data.fd = fd1;
epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,&ev);
ev.events = 0;
ev.data.fd = fd2;
epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,&ev);
while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
{
//布置监视任务
//读集设置为空集
ev.data.fd =fd1;
ev.events = 0;
//epoll_ctl(epfd,EPOLL_CTL_MOD);
if (fsm12.state == STATE_R)
ev.events |= EPOLLIN;
if (fsm21.state == STATE_W)
ev.events |= EPOLLOUT;
epoll_ctl(epfd,EPOLL_CTL_MOD,fd1,&ev);
ev.data.fd =fd2;
ev.events = 0;
if (fsm21.state == STATE_R)
ev.events |= EPOLLOUT;
if (fsm12.state == STATE_W)
ev.events |= EPOLLIN;
//监视
if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
{
while(epoll_wait(epfd,&ev,1,-1)<0)
{
if (errno == EINTR)
continue;
perror("epoll_wait()");
exit(1);
}
}
//查看监视结果
if(ev.data.fd == fd1 &&ev.events &EPOLLIN\
||ev.data.fd == fd2&&ev.events&EPOLLOUT\
||fsm12.state > STATE_AUTO)
fsm_driver(&fsm12);
if(ev.data.fd == fd2 &&ev.events &EPOLLIN\
||ev.data.fd == fd2&&ev.events&EPOLLOUT\
||fsm12.state > STATE_AUTO)
fsm_driver(&fsm21);
}
/*恢复之前的状态*/
fcntl(fd1,F_SETFL,fd1_save);
fcntl(fd2,F_SETFL,fd2_save);
close(epfd);
}
int main()
{
int fd1,fd2;
fd1 = open(TTY1,O_RDWR);
if (fd1<0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
if (fd2<0)
{
perror("open()");
exit(1);
}
write(fd2,"TTY2\n",5);
relay(fd1,fd2);
close(fd2);
close(fd1);
exit(0);
}
3、其他读写函数
readv();//读写可以碎片化
writev();
readn();//unix的独家函数
writen();
4、存储映射IO
mmap() &&munmap()示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
int main(int argc,char **argv)
{
int fd,count=0;
/*获取文件字节长度的结构体*/
struct stat statres;
char* str;
if(argc<2)
{
fprintf(stderr,"Usage...\n");
exit(1);
}
fd = open(argv[1],O_RDONLY);
if (fd<0)
{
perror("open()");
exit(1);
}
if (fstat(fd,&statres)<0)
{
perror("fstat()");
exit(1);
}
str = mmap(NULL,statres.st_size,PROT_READ,MAP_SHARED,fd,0);
if (str == MAP_FAILED)
{
perror("mmap()");
exit(1);
}
close(fd);
for (int i = 0; i < statres.st_size; i++)
{
if (str[i] == 'a')
count++;
}
printf("%d\n",count);
munmap(str,statres.st_size);
exit(1);
}
共享内存的实现
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <string.h>
#define MEMSIZE 1024
int main(int argc,char **argv)
{
char *ptr;
pid_t pid;
ptr = mmap(NULL,MEMSIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
if (ptr == MAP_FAILED)
{
perror("mmap()");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork()");
munmap(ptr,MEMSIZE);
exit(1);
}
if (pid == 0) //child write
{
strcpy(ptr,"hello!");
munmap(ptr,MEMSIZE);
exit(0);
}
else //parent read
{
wait(NULL);
puts(ptr);
munmap(ptr,MEMSIZE);
exit(0);
}
}
5、文件锁
fcntl();
lockf();
flock();
lockf();示例 多进程取代多线程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define PROCNUM 20
#define FNAME "/tmp/out"
#define LINESIZE 1024
char linebuf[LINESIZE];
static void func_add(void)
{
FILE *fp;
int fd;
fp = fopen(FNAME,"r+");
if (fp == NULL)
{
perror("fopen()");
exit(1);
}
fd = fileno(fp);
lockf(fd,F_LOCK,0);
fgets(linebuf,LINESIZE,fp);
fseek(fp,0,SEEK_SET);
sleep(1);
fprintf(fp,"%d\n",atoi(linebuf)+1);
fflush(fp);
lockf(fd,F_ULOCK,0);
fclose(fp);
}
int main()
{
int err,i;
pid_t pid;
for ( i = 0; i < PROCNUM; i++)
{
fork();
if (pid<0)
{
perror("fork()");
exit(1);
}
if (pid == 0)
{
func_add();
exit(0);
}
}
for ( i = 0; i < PROCNUM; i++)
wait(NULL);
exit(0);
}