QQ
QQ
posts - 2,comments - 1,trackbacks - 0
#include <sys/types.h>
#include 
<sys/stat.h>
#include 
<fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
pathname是C风格字符串表示的全路径名
flags指定文件应该如何打开,并包括逻辑"与"操作的一个或多个以下标志:
O_RDONLY 以只读的方式打开文件
O_WRONLY 以只写的方式打开文件
O_RDWR 以读写的方式打开文件
O_APPEND 以追加的方式打开文件
O_CREAT 如果文件不存在,则创建一个文件
mode在新文件创建时指定其访问权限,当flags指定为O_CREAT时,必须提供该参数。当flags不为O_CREAT时,该参数被忽略。注意该访问权限只对将来对该新文件的访问有效。
O_EXEC 如果使用了O_CREAT,并且文件已经存在,就会发生一个错误,如果没有使用O_CREAT,则行为未定义
O_TRUNC 如果文件已经存在,并是一个普通文件,访问模式可写,,则删除其中内容
O_NOBLOCK 以非阻塞的方式打开一个文件

O_ASYNC
O_CLOEXEC
O_DIRECT
O_DIRECTORY
O_LARGEFILE
O_NOATIME
O_NOCTTY
O_NOFOLLOW
O_NONBLOCK , O_NDELAY
O_SYNC

返回值:成功返回文件描述字,失败返回-1,并设置合适的errno

#include <unistd.h>

ssize_t read(
int fd, void *buf, size_t count);
ssize_t write(
int fd, const void *buf, size_t count);
参数:fd:文件描述符 buf:用来存放数据的目的缓冲区 count:要读取的字节数
返回值:-1 遇到错误
                num_read 实际成功读取的字节数(不一定等于count),读后文件当前指针向后移动 count 个字节
注意:如果count为0,read()返回0,并没有其他结果,如果count大于SSIZE_MAX,结果将不确定。
#include <sys/types.h>
#include 
<unistd.h>

off_t lseek(
int fd, off_t offset, int whence);

#include <unistd.h>
#include 
<fcntl.h>

int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);


#include <unistd.h>

int close(int fd);

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

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

#include <sys/types.h>
#include 
<sys/stat.h>

mode_t umask(mode_t mask);

#include <sys/stat.h>
#include 
<sys/types.h>

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

posted @ 2009-03-01 09:28 nichii 阅读(270) | 评论 (0)编辑 收藏
管道的问题在于它们只能在具有共同祖先(指父子进程关系)的进程间使用,不过该问题已随有名管道(FIFO)的引入而解决。
管道和FIFO都是随进程持续的:一直存在到打开着该对象(管道或FIFO)的最后一个进程关闭该对象为止。
管道没有名字,因此不能用于无亲缘关系的进程间通信。
FIFO有一个在文件系统中的Unix路径名作为其标识符,因此可用于无亲缘关系的进程间通信。
管道和FIFO都可以用通常的read和write函数访问。
1.管道
所有的Unix都提供管道。它由pipe函数创建,提供一个单向数据流。
#include <unistd.h>

int pipe(int pipefd[2]);

/**
*函数描述: pipe()创建一个单向的数据通道用于进程间通信
*pipefd[0]返回管道的读取端描述字
*pipefd[1]返回管道的写入端描述字
*
*返回值: 成功返回0;失败返回-1,错误原因存放errno中
*
*错误:
*    EMFILE 进程已用完文件描述词最大量
*    ENFILE 系统已无文件描述词可用
*    EFAULT 参数 filedes 数组地址不合法
*/
范例
 1#include <sys/wait.h>
 2#include <assert.h>
 3#include <stdio.h>
 4#include <stdlib.h>
 5#include <unistd.h>
 6#include <string.h>
 7
 8int main(int argc, char *argv[])
 9{
10    int pipefd[2];
11    pid_t cpid;
12    char buf;
13
14    assert(argc == 2);
15
16    if(pipe(pipefd) == -1)
17    {
18        perror("pipe");
19        exit(EXIT_FAILURE);
20    }

21
22    cpid = fork();
23    if(cpid == -1)
24    {
25        perror("fork");
26        exit(EXIT_FAILURE);
27    }

28
29    if(cpid == 0)
30    {
31                //子进程关闭写入端描述字
32        close(pipefd[1]);
33
34        while(read(pipefd[0], &buf, 1> 0)
35        {
36            write(STDOUT_FILENO, &buf, 1);
37        }

38
39        write(STDOUT_FILENO, "\n"1);
40        close(pipefd[0]);
41        _exit(EXIT_SUCCESS);
42    }

43    else
44    {
45                //父进程关闭读取端描述字,将命令行参数2传送给子进程
46        clese(pipefd[0]);
47        write(pipefd[1], argv[1], strlen(argv[1]));
48        close(pipefd[1]);  //读取端将读取EOF
49        wait(NULL);        //等待子进程结束
50        exit(EXIT_SUCCESS);
51    }

52}

53

编译运行:

xxx@linux:~/ipcs> gcc -Wall pipe1.c -o pipe1
xxx@linux:
~/ipcs> ./pipe1 hellopipe
hellopipe

popen()/pclose()函数
#include <stdio.h>

FILE 
*popen(const char *command, const char *type);

int pclose(*stream);

描述
popen() 函数用创建管道的方式启动一个进程, 并调用shell. 因为管道是被定义成单向的, 所以type 参数只能定义成只读或者 只写, 不能是 两者同时, 结果流也相应的是只读或者只写.
command 参数是一个字符串指针, 指向的是一个以null 结束符结尾的字符串, 这个字符串包含一个shell 命令. 这个命令被送到/bin/sh 以 -c 参数 执行, 即由shell 来执行. type 参数也是一个指向以null 结束符结尾的字符串的指针, 这个字符串必须是'r' 或者'w’ 来指明是读还是写.

popen() 函数的返回值是一个普通的标准I/O流, 它只能用pclose() 函数来关闭, 而不是fclose()函数. 向这个流的写入被转化为 对command 命令的标准输入; 而command 命令的标准输出则是和调用popen(), 函数的进程相同,除非这个被command命令 自己改变. 相反的, 读取 一个“被popen了的” 流, 就相当于读取 command 命令的标准输出, 而 command 的标准输入则是和 调用popen, 函数的进程相同.

注意, popen 函数的输出流默认是被全缓冲的.

pclose函数等待相关的进程结束并返回一个 command 命令的退出状态, 就像 wait4 函数一样.

返回值
如果 fork(2) 或者 pipe(2) 调用失败, 或者它分配不到内存, popen 函数返回 NULL .
如果 wait4 返回一个 错误, 或者 其他什么错误 发生, pclose 函数返回一个 -1.

错误
如果内存空间开辟失败, popen 函数并不设置 errno . 如果内部的 fork() 函数或者pipe() 函数失败, errno 则会被适当的设置.
如果type 参数是不可用的, 而且这个状态被侦测到, errno 将被设置成 EINVAL.
如果pclose() 函数不能侦测到子进程的状态, errno 将被设置成 ECHILD.

BUGS
因为 command 命令 读取的 标准输入 和 调用 popen() 函数 的 进程 共享 一个 “搜索偏移量”, 所以, 如果 原进程 已经 完成了 一个 缓冲的读取, 那么 command 命令的 输入位置 将是 不可预料的. 相似的, command 命令的 输出 会和 原进程的输出 混杂在一起. 后者 可以 在调用 popen. 函数前 调用 fflush(3) 函数 来避免.
范例

 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4int main(int argc, char *argv[])
 5{
 6    char buf[128];
 7    FILE *pp;
 8
 9    if((pp = popen("ls -l""r")) == NULL)
10    {
11        perror("popen");
12        exit(EXIT_FAILURE);
13    }

14
15    while(fgets(buf, sizeof(buf), pp))
16    {
17        printf("%s", buf);
18    }

19
20    pclose(pp);
21
22    exit(EXIT_SUCCESS);    
23}

24


2.FIFO
管道没有名字,无亲缘关系的两个进程无法创建一个彼此间的管道并用于IPC(不考虑使用描述字传递)。
FIFO指代先进先出,Unix中的FIFO类似于管道。它是一个单向(半双工)数据流。不同于管道的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程访问同一个FIFO。FIFO也称为有名管道(named pipe)

#include <sys/types.h>
#include 
<sys/stat.h>

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

其中pathname是一个普通的Unix路径名,它是该FIFO的名字。
mode参数指定文件权限位,类似open的第三个参数。
成功返回0 ,失败返回-1;
错误代码
    EACCESS 参数pathname所指定的目录路径无可执行的权限
    EEXIST 参数pathname所指定的文件已存在。
    ENAMETOOLONG 参数pathname的路径名称太长。
    ENOENT 参数pathname包含的目录不存在
    ENOSPC 文件系统的剩余空间不足
    ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
    EROFS 参数pathname指定的文件存在于只读文件系统内。

范例


 

posted @ 2009-02-28 18:12 nichii 阅读(414) | 评论 (1)编辑 收藏
仅列出标题