首页 > 技术文章 > 14.有名管道通信

FORFISH 2016-02-14 08:35 原文

14.有名管道通信

有名管道:

有名管道又称为FIFO文件,因此我们对有名管道的操作可以采用操作文件的方法,如使用

open,read,write等.

有名管道的学习:

 

有名管道与其他文件的对比:

FIFO文件在使用上和普通文件有相似之处,但是也有不同之处:

1. 读取Fifo文件的进程只能以"RDONLY"方式打开fifo文件。

2. 写Fifo文件的进程只能以"WRONLY"方式打开fifo文件。

3. Fifo文件里面的内容被读取后,就消失了。但是普通文件里面的内容读取后还存在。

 

创建有名管道:man 3 mkfifo:

NAME

mkfifo - make a FIFO special file (a named pipe)

 

SYNOPSIS

#include <sys/types.h>

#include <sys/stat.h>

 

int mkfifo(const char *pathname, mode_t mode);

 

DESCRIPTION

mkfifo() makes a FIFO special file with name pathname. mode specifies the

FIFO's permissions. It is modified by the process's umask in the usual way:

the permissions of the created file are (mode & ~umask).

 

A FIFO special file is similar to a pipe, except that it is created in a dif-

ferent way. Instead of being an anonymous communications channel, a FIFO spe-

cial file is entered into the file system by calling mkfifo().

 

Once you have created a FIFO special file in this way, any process can open it

for reading or writing, in the same way as an ordinary file. However, it has

to be open at both ends simultaneously before you can proceed to do any input

or output operations on it. Opening a FIFO for reading normally blocks until

some other process opens the same FIFO for writing, and vice versa. See

fifo(7) for non-blocking handling of FIFO special files.

 

RETURN VALUE

On success mkfifo() returns 0. In the case of an error, -1 is returned (in

which case, errno is set appropriately).

 

ERRORS

EACCES One of the directories in pathname did not allow search (execute) per-

mission.

 

EEXIST pathname already exists. This includes the case where pathname is a

symbolic link, dangling or not.

 

ENAMETOOLONG

Either the total length of pathname is greater than PATH_MAX, or an

individual filename component has a length greater than NAME_MAX. In

the GNU system, there is no imposed limit on overall filename length,

but some file systems may place limits on the length of a component.

 

ENOENT A directory component in pathname does not exist or is a dangling sym-

bolic link.

 

ENOSPC The directory or file system has no room for the new file.

 

ENOTDIR

A component used as a directory in pathname is not, in fact, a direc-

tory.

 

EROFS pathname refers to a read-only file system.

 

CONFORMING TO

POSIX.1-2001.

 

SEE ALSO

mkfifo(1), close(2), open(2), read(2), stat(2), umask(2), write(2), mkfi-

foat(3), fifo(7)

 

COLOPHON

This page is part of release 3.22 of the Linux man-pages project. A descrip-

tion of the project, and information about reporting bugs, can be found at

http://www.kernel.org/doc/man-pages/.

创建有名管道的函数名:mkfifo:

原型:int mkfifo(const char *pathname, mode_t mode);

该函数的功能是创建一个有名管道,即是一个fifo文件。

需要的头文件:

#include <sys/types.h>

#include <sys/stat.h>

返回值:成功返回0,失败是返回-1.

参数说明:

pathname:要创建的fifo文件的名字,带路径的。

mode:创建的fifo文件的访问权限

 

删除有名管道:

查看信息:man 2 unlink:

NAME

unlink - delete a name and possibly the file it refers to

 

SYNOPSIS

#include <unistd.h>

 

int unlink(const char *pathname);

 

DESCRIPTION

unlink() deletes a name from the file system. If that name was the last link

to a file and no processes have the file open the file is deleted and the space

it was using is made available for reuse.

 

If the name was the last link to a file but any processes still have the file

open the file will remain in existence until the last file descriptor referring

to it is closed.

 

If the name referred to a symbolic link the link is removed.

 

If the name referred to a socket, fifo or device the name for it is removed but

processes which have the object open may continue to use it.

 

RETURN VALUE

On success, zero is returned. On error, -1 is returned, and errno is set

appropriately.

 

ERRORS

EACCES Write access to the directory containing pathname is not allowed for the

process's effective UID, or one of the directories in pathname did not

allow search permission. (See also path_resolution(7).)

 

EBUSY (not on Linux)

The file pathname cannot be unlinked because it is being used by the

system or another process and the implementation considers this an

error.

 

EFAULT pathname points outside your accessible address space.

 

EIO An I/O error occurred.

 

EISDIR pathname refers to a directory. (This is the non-POSIX value returned

by Linux since 2.1.132.)

 

ELOOP Too many symbolic links were encountered in translating pathname.

 

ENAMETOOLONG

pathname was too long.

 

ENOENT A component in pathname does not exist or is a dangling symbolic link,

or pathname is empty.

 

ENOMEM Insufficient kernel memory was available.

 

ENOTDIR

A component used as a directory in pathname is not, in fact, a direc-

tory.

 

EPERM The system does not allow unlinking of directories, or unlinking of

directories requires privileges that the calling process doesn't have.

(This is the POSIX prescribed error return; as noted above, Linux

returns EISDIR for this case.)

 

EPERM (Linux only)

The file system does not allow unlinking of files.

 

EPERM or EACCES

The directory containing pathname has the sticky bit (S_ISVTX) set and

the process's effective UID is neither the UID of the file to be deleted

nor that of the directory containing it, and the process is not privi-

leged (Linux: does not have the CAP_FOWNER capability).

 

EROFS pathname refers to a file on a read-only file system.

 

CONFORMING TO

SVr4, 4.3BSD, POSIX.1-2001.

 

BUGS

Infelicities in the protocol underlying NFS can cause the unexpected disappear-

ance of files which are still being used.

 

SEE ALSO

rm(1), chmod(2), link(2), mknod(2), open(2), rename(2), rmdir(2), unlinkat(2),

mkfifo(3), remove(3), path_resolution(7), symlink(7)

 

COLOPHON

This page is part of release 3.22 of the Linux man-pages project. A descrip-

tion of the project, and information about reporting bugs, can be found at

http://www.kernel.org/doc/man-pages/.

该函数的原型:

int unlink(const char *pathname);

需要的头文件:unistd.h.

该函数的功能是删除文件。

执行成功则返回0,失败是返回-1.

参数说明:

pathname:用来指定要删除的文件名字(含路径)。

 

到这里我们就知道了管道的一系列的操作。现在写两个独立进程利用有名管道来通信。写进程的功能是创建FIFO管道,同时写入数据。读进程则是读取fifo里的数据,显示读出的数据。看看写入和读出是否一致。

 

 

 

 

 

 

首先实现写有名管道的程序:write.c:

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

 

void main(){

    int fd;

 

    //reate fifo file

    mkfifo("/home/jin",0666);

    //open fifo file    

    fd = open("/home/jin",O_WRONLY);

    //write data into fifo file

    write(fd,"forfish",8);

    close(fd);

 

}

 

上面是往一个命名管道写数据。

 

有名管道的read.c:

#include <sys/types.h>

#include <sys/stat.h>

#include <stdio.h>

#include <fcntl.h>

 

void main(){

    char my_buf[15];

    int fd;

 

    fd = open("/home/jin",O_RDONLY);

    read(fd,my_buf,8);

    printf("read %s \n",my_buf);

    close(fd);

    unlink("/home/jin");

}

这是有名管道的读出数据。

执行的过程:

先执行write.c:如下,有名管道的写数据进入等待进程把数据读出,进入阻塞状态。这也是命名管道的一个特点。

上面的过程,当我们运行了读进程。从命名管道读出数据后,write进程的阻塞状态也结束了。

 

推荐阅读