管道
==================================================================
pipe (建立管道)
头文件:
#include <unistd.h>
定义函数:
int pipe(int filedes[2]);
函数说明 :
-
pipe()会建立管道, 并将文件描述词由参数 filedes 数组返回. filedes[0]为管道里的读取端,
filedes[1]则为管道的写入端.
返回值:
-
若成功则返回零, 否则返回-1, 错误原因存于 errno 中.
错误代码 EMFILE 进程已用完文件描述词最大量.
ENFILE 系统已无文件描述词可用.
EFAULT 参数 filedes 数组地址不合法.
DEMO:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
//函数声明
void func(void);
int main(int argc, char const *argv[])
{
//创建一个无名管道 filedes[0]读取端 filedes[1]写入端
int filedes[2];
int ret = pipe(filedes);
if(-1 == ret)
{
perror("pipe error\n");
return -1;
}
//创建一个子进程
pid_t x = fork();
//子进程
if(x == 0)
{
printf("[%d]this is child process\n", (int)getpid());
//往无名管道写入端写
char *buf = malloc(25);
printf("child:");
//从键盘输入
bzero(buf, 25);
fgets(buf, 25, stdin);
write(filedes[1], buf, strlen(buf));
}
//父进程
if(x > 0)
{
printf("[%d]this is father process\n", (int)getpid());
//等待子进程退出
wait(NULL);
//从无名管道读取端读
char *buf = malloc(25);
bzero(buf, 25);
read(filedes[0], buf, 25);
printf("[%d]从无名管道子进程中读到的内容:%s",
(int)getpid(), buf);
}
ret = atexit(func);
if(-1 == ret)
{
perror("atexit error\n");
}
#ifdef _EXIT
_exit(0); //直接退出
#else
exit(0); //正常退出
#endif
}
void func(void)
{
printf("[%d]eixt succeed\n", (int)getpid());
}
==================================================================
mkfifo ( 建立具名管道 )
头文件:
#include <sys/types.h>
#include <sys/stat.h>
定义函数 :
int mkfifo(const char * pathname, mode_t mode);
函数说明 :
- mkfifo()会依参数 pathname 建立特殊的 FIFO 文件, 该文件必须不存在, 而参数 mode 为该文件的权限 (mode%~umask), 因此 umask 值也会影响到 FIFO 文件的权限. Mkfifo()建立的 FIFO 文件其他进程都可以用读写一般文件的方式存取. 当使用 open()来打开 FIFO 文件时, O_NONBLOCK 旗标会有影响
-
当使用 O_NONBLOCK 旗标时, 打开 FIFO 文件来读取的操作会立刻返回, 但是若还没有其他进
程打开 FIFO 文件来读取, 则写入的操作会返回 ENXIO 错误代码. - 没有使用 O_NONBLOCK 旗标时, 打开 FIFO 来读取的操作会等到其他进程打开 FIFO 文件来写入才正常返回. 同样地, 打开 FIFO 文件来写入的操作会等到其他进程打开 FIFO 文件来读取后才正常返回.
返回值 :
-
若成功则返回 0, 否则返回-1, 错误原因存于 errno 中.
错误代码 EACCESS 参数 pathname 所指定的目录路径无可执行的权限
EEXIST 参数 pathname 所指定的文件已存在.
ENAMETOOLONG 参数 pathname 的路径名称太长.
ENOENT 参数 pathname 包含的目录不存在
ENOSPC 文件系统的剩余空间不足
ENOTDIR 参数 pathname 路径中的目录存在但却非真正的目录.
EROFS 参数 pathname 指定的文件存在于只读文件系统内.
==================================================================
access ( 判断是否具有存取文件的权限 )
头文件 :
#include <unistd.h>
定义函数 :
int access(const char * pathname, int mode);
函数说明 :
- access()会检查是否可以读/写某一已存在的文件. 参数 mode 有几种情况组合, R_OK, W_OK, X_OK和 F_OK. R_OK, W_OK 与 X_OK 用来检查文件是否具有读娶写入和执行的权限. F_OK 则是用来判断该文件是否存在. 由于 access()只作权限的核查, 并不理会文件形态或文件内容, 因此, 如果一目录表示为”可写入”, 表示可以在该目录中建立新文件等操作, 而非意味此目录可以被当做文件处理. 例如, 你会发现 DOS 的文件都具有”可执行”权限, 但用 execve()执行时则会失败.
返回值:
- 若所有欲查核的权限都通过了检查则返回 0 值, 表示成功, 只要有一权限被禁止则返回-1.
以下两个demo都得运行
DEMO1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define FIFO_PATH "/tmp/xxno/mkfifo"
#define BUF_SIZE 30
int main(int argc, char const *argv[])
{
//创建有名管道文件:
if(access(FIFO_PATH, F_OK | W_OK))
{
int ret = mkfifo(FIFO_PATH, 0666);
if(-1 == ret)
{
perror("mkfifo error\n");
return -1;
}
}
//打开管道文件:
int fd_fifo = open(FIFO_PATH, O_WRONLY);
if(-1 == fd_fifo)
{
perror("open error\n");
return -1;
}
while(1)
{
//往管道文件里写内容:
char *buf = malloc(BUF_SIZE);
printf("写入管道中:\n");
fgets(buf, BUF_SIZE, stdin);
write(fd_fifo, buf, strlen(buf));
}
//关闭管道文件:
close(fd_fifo);
return 0 ;
}
DEMO2:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define FIFO_PATH "/tmp/xxno/mkfifo"
#define BUF_SIZE 30
int main(int argc, char const *argv[])
{
//创建有名管道文件:
if(access(FIFO_PATH, F_OK | R_OK))
{
int ret = mkfifo(FIFO_PATH, 0666);
if(-1 == ret)
{
perror("mkfifo error\n");
return -1;
}
}
//打开管道文件:
int fd_fifo = open(FIFO_PATH, O_RDONLY);
if(-1 == fd_fifo)
{
perror("open error\n");
return -1;
}
//往管道文件里写内容:
while(1)
{
char *buf = malloc(BUF_SIZE);
int ret = read(fd_fifo, buf, BUF_SIZE);
if(0 == ret)
{
break;
}
printf("%s\n", buf);
}
//关闭管道文件:
close(fd_fifo);
return 0 ;
}