您的位置:首页 > 产品设计 > UI/UE

apue 02 管道 定时器

2014-01-05 19:29 162 查看
1. 从文件中读取数据写入FIFO

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

#define TEST_SIZE 68*1024

int main(void)
{
mkfifo("tp", 0644);
int infd;
infd = open("test.txt", O_RDONLY);
if (infd == -1)
ERR_EXIT("open");

int outfd;
outfd = open("tp", O_WRONLY);
if (outfd == -1)
ERR_EXIT("open");

char buf[1024];
int n;
while ((n=read(infd, buf, 1024))>0)
{
write(outfd, buf, n);
}
close(infd);
close(outfd);

return 0;
}


2. 从FIFO中读数据然后写入文件

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

int main(int argc, char *argv[])
{
int outfd;
outfd = open("t.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (outfd == -1)
ERR_EXIT("open");

int infd;
infd = open("tp", O_RDONLY);
if (outfd == -1)
ERR_EXIT("open");

char buf[1024];
int n;
while ((n=read(infd, buf, 1024))>0)
{
write(outfd, buf, n);
}
close(infd);
close(outfd);
unlink("tp");

return 0;
}


3.计算管道PIPE的大小

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void handler(int sig)
{
printf("%d\n",sig);
}
int main(int argc, char *argv[])
{

int pipefd[2];
if(-1 ==pipe(pipefd))
ERR_EXIT("pipe error");

//使用fcntl通过文件描述符来设置文件的属性
int flags = fcntl(pipefd[1], F_GETFL);
flags |= O_NONBLOCK;
fcntl(pipefd[1], F_SETFL, flags);

int ret;
int count = 0;
while(1)
{
ret = write(pipefd[1], "A", 1);  // 一直写直到阻塞
if(-1 == ret)
{
printf("err=%s", strerror(errno));
break;
}
++count;
}
printf("count=%d\n", count);
return 0;
}


4.使用读写stdin,stdout重定位实现文件的拷贝

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

int main(int argc, char *argv[])
{
//    这里进行了重定位
close(0);                                    //    1. close   stdin 关闭读端 使其指向 hello.c
open("./hello.c", O_RDONLY);
close(1);                                    //    2. close   stdout   关闭写端 使其指向 hello2.c
open("./hello2.c", O_WRONLY | O_CREAT | O_TRUNC, 0644);

execlp("cat", "cat", NULL);         //    3. cat 不带参数时 将stdin标准输入拷贝到标准输出stdout  实现了文件的拷贝

return 0;
}


5.管道概念

1.管道
·本质有固定大小的内核缓冲区
·特点:
@半双工 单向
@只能用于有共同祖先的进程通信
·#include <unistd.h>
int pipe(int fd[2])
·fd[1] 写端
·fd[0] 读端

2.当管道满的时候
  O_NONBLOCK disable: write调用阻塞 即进程暂停执行 一直等到有数据来到为止
  O_NONBLOCK enable: 返回-1 EAGAIN 调用返回-1 errno值为EAGAIN

3.当管道满时
  如果是阻塞的则write()函数调用阻塞 知道有进程读走数据
  如果为非阻塞 调用-1 errno 值为EAGAIN

4.如果写或读有关闭的
  read 返回0 write会产生SIGPIPE信号

5.当写入的数据小于PIPE_BUF(4K) linux将保证写入的原子性 否则不保证

6.匿名管道有限制就是需要共同的祖先进程才能通信
  命名管道FIFO不需要 用于不相关的进程通信 是一种特殊类型的文件
  如果有度或写一个未打开 则默认会阻塞操作会阻塞

6. 非阻塞管道的读写

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

int main(int argc, char *argv[])
{
int pipe_fd[2];
if(-1 == pipe(pipe_fd))
{
ERR_EXIT("pipe error");
}
pid_t pid;
pid = fork();
if(-1 == pid)
ERR_EXIT("pipe error");
if(0 == pid)//child process
{
sleep(3);
close(pipe_fd[0]);  // 这里子进程关闭的它的读端 因为拷贝后 父子进程分开了
write(pipe_fd[1], "hello pipe \n", 12);
close(pipe_fd[1]);
exit(EXIT_SUCCESS);
}

close(pipe_fd[1]);
char buf[12] = {0};

//set nonblock
int flags = fcntl(pipe_fd[0], F_GETFL);
fcntl(pipe_fd[0], F_SETFL, flags | O_NONBLOCK);
int ret =read(pipe_fd[0], buf, 12);
if(-1 == ret )
ERR_EXIT("read error");

printf("read pipe == %s \n ", buf);

return 0;
}


7.管道的简单读写

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

int main(int argc, char *argv[])
{
int pipe_fd[2];
if(-1 == pipe(pipe_fd))
{
ERR_EXIT("pipe error");
}
pid_t pid;
pid = fork();
if(-1 == pid)
ERR_EXIT("pipe error");
if(0 == pid)//child process
{
close(pipe_fd[0]);
write(pipe_fd[1], "hello pipe \n", 12);
close(pipe_fd[1]);
exit(EXIT_SUCCESS);
}

close(pipe_fd[1]);
char buf[12] = {0};
read(pipe_fd[0], buf, 12);

printf("read pipe == %s", buf);

return 0;
}


8.时间的函数
sleep

·while(n = sleep(time))//返回剩余的秒数

·do

{

  n = sleep(n);

}while(n>0)


usleep

nanosleep(const struct timespec* req, struc timespec *rem)

struct timespec{

time_t tv_sec; /* seconds */

long tv_nsec; /* nanoseconds */

};

struct timeval{

long tv_sec;

long tv_usec;

};


9.定时器的使用 alarm()

alarm()可以产生SIGALARM信号

setitimer() 间歇性的产生SIGALARM信号

#include <sys/time.h>

int getitimer(int which, struct itimerval *curr_value);//获取剩余的时间 剩余多久会产生信号

int setitimer(int which, const struct itimerval *new_value,

struct itimerval *old_value);

struct itimerval {

struct timeval it_interval; /* next value */

struct timeval it_value;    /* current value */

};

struct timeval {

long tv_sec;                /* seconds */

long tv_usec;               /* microseconds */

};


10. setitimer() getitimer() 设置定时器

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

void handler(int sig)
{
printf("recv a sig=%d\n", sig);
}

int main(int argc, char *argv[])
{
if (signal(SIGALRM, handler) == SIG_ERR)
ERR_EXIT("signal error");

struct timeval tv_interval = {1, 0};
struct timeval tv_value = {5, 0};
struct itimerval itimev;

itimev.it_interval = tv_interval;
itimev.it_value = tv_value;

setitimer(ITIMER_REAL, &itimev, NULL);

int i;
for (i=0; i<10000; i++);

struct itimerval oit;
setitimer(ITIMER_REAL, &itimev, &oit);

getitimer(ITIMER_REAL, &itimev); //  得到剩余定时器的响应时间
printf("%d %d %d %d\n", (int)itimev.it_interval.tv_sec, \
(int)itimev.it_interval.tv_usec, (int)itimev.it_value.tv_sec, \
(int)itimev.it_value.tv_usec);
for (;;)
pause();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: