文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>今天还多充实

今天还多充实

时间:2006-01-09  来源:晏东

2006年1月10日星期一                         阴见多云

一、    进程间通信

a)      双工管道

输入始终是fd[1],输出是fd[0],其他的不用管。因此如果是将数据从父进程发到子进程:

parent process: close(fd[0]);write(fd[1]);

child  process:close(fd[1]);read(fd[0]);

即兴练习:

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

 

int main()

{

      int fd[2];

      pid_t pid;

      char buf[100];

      strcpy(buf, "hello child process!\n");

      pipe(fd);

     

      if ((pid=fork()) < 0)

           exit(-1);

      else if (pid == 0)

      {

           close(fd[1]);

           read(fd[0], buf, sizeof(buf));

           printf("recv from parent process:%s", buf);

           exit(0);

      }else

      {

           close(fd[0]);

           write(fd[0], buf, sizeof(buf));

      }

      exit(0);

}

      以上程序示意图为:

规则如下:

1)         如果从fd[0]读数据,读完后read返回0

2)         如果fd[1]关闭,而向起写数据则,产生SIGPIPE,忽略或捕捉此信号产生EPIPE错误。

文件描述符dup2原型:

      #include <unistd.h>

      int dup2(int oldfd, int newfd);

      成功返回新的文件描述符,调用失败返回-1,其他返回错误码。例:

      dup2(0, fd[1]);//将标准输入复制到管道的fd[1],同时关闭标准输入0。

 

快速建立管道popen:

      #include <stdio.h>

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

其中:cmd是shell命令,type中只取其第一个字符(r/w)。默认情况下,w说明是向shell输入命令(***|cmd),执行结果到标准输出;r说明是shell的执行结果,然后输出到标准输出。

例:sort的popen+w使用

int main()

{

      FILE *pipe_f;

      char *strs[5] = {"a", "b", "d", "c", "e"};

      pipe_f = popen("sort", "w");

     

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

      {

           fputs(strs[i], pipe_f);

           fputs("\n", pipe_f);

      }

     

      pclose(pipe_f);

     

      exit(0);

}

sort的popen+r使用:

int main()

{

      FILE *pipe_f;

      char strs[200][200];

      pipe_f = popen("ls|sort", "r");

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

      {

           if (fgets(strs[i], 200, pipe_f))

                 printf("%s", strs[i]);

           else break;

      }

     

      pclose(pipe_f);

     

      exit(0);

}

以上调用和shell调用完全一样!!

注意:popen操作是自动操作,在linux下PIPE_BUF为4096,在posix下是512,如果读取和写入的字节数在此限制以下,则进行自动操作,否则不行。

           在使用过程中,可以建立两个半双工管道,一个用于读,一个用于写。在使用半双工管道时,父进程中建立的pipe,只能在次父进程的衍生进程使用,说明半双工具有局部衍生性。

b)      FIFO命名管道

                       i.              利用mknod建立FIFO管道

int mknod(char *filepath, mode_t mode, dev_t dev);

成功返回0;失败-1;其他errno.

示例:

umask(0);//临时清空umask

mknod(“./myfifo”, S_IFIFO | 0666, 0);

                    ii.              FIFO建立后一般放在后台,等待客户端,示例:

int main(int argc, char *argz[])

{

/*   //server

      FILE *fp;

      char readbuf[80];

     

      umask(0);

      mknod("./myfifo", S_IFIFO | 0666, 0);

      while(1)

      {

           fp = fopen("./myfifo", "r");

           fgets(readbuf, 80, fp);

           printf("Receive Data from FIFO:%s\n", readbuf);

           fclose(fp);

      }

*/

      //client

     

      FILE *fp;

      fp = fopen("./myfifo", "w");

     

      fputs(argz[1], fp);

      exit(0);

}

                 iii.              注意:一个FIFO管道写打开后即进入阻塞,直到数据的到来,如果不想阻塞须调用open()设置O_NONBLOCK选项。此外,一个FIFO管道必须同时有读写进程,如果只有写,没有读,就会产生SIGPIPE。

c)      消息队列

                       i.              IPC关键字,产生示例:

Key_t key;

Key = ftok(“.”, ‘a’);

成功返回关键字,失败返回-1,可以使用stat()获得错误信息。

                    ii.              消息缓冲区

struct msgbuf{

      long mtype;

      (other data);

}//other data为自定义类型

msgbuf最大字节数为4056(包括long mtype),实际最大内容为4052

                 iii.              创建或者取一个消息队列msgget()

原型:int msgget(key_t key, int msgflag);

成功返回0,失败返回-1:errno;

IPC_CREAT用于创建或取已有队列

IPC_EXCL和IPC_CREAT连用时,只能用于创建新的队列

                  iv.              练习:通过消息队列,由一个父进程发送到一个子进程。(终于在下班前编译运行通过,我真的是猪,尽犯低级错误)

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>

struct mymsgbuf{

      long mtype;

      char data[20];

};

int main()

{

      key_t key;

      pid_t pid;

      int qid;

      struct mymsgbuf sndmsgbuf;

      struct mymsgbuf rcvmsgbuf;

      //data initialize

      sndmsgbuf.mtype = 1;

      strcpy(sndmsgbuf.data, "Queue message!");

      printf("Prepare:%s\n", sndmsgbuf.data);

      //ganerate key

      key = ftok(".", 'm');

      //create

      if ((qid = msgget(key, IPC_CREAT | IPC_EXCL | 0666)) ==-1)

      {

           perror("msgget error");

           exit(-1);   

      }

      if ((pid = fork()) < 0)

      {

           perror("fork");

           exit(-1);

      }else if (pid > 0)

      {

           //send

           if (msgsnd(qid, &sndmsgbuf, sizeof(struct mymsgbuf)-sizeof(long), 0/*IPC_NOWAIT*/) == -1)

           {

                 perror("msgsnd error");

                 exit(-1);

           }

      }else

      {

           if (msgrcv(qid, &rcvmsgbuf, sizeof(struct mymsgbuf)-sizeof(long), 0, 0) == -1)

           {

                 perror("msgrcv error");

                 exit(-1);

           }

           printf("Data rcv from parent:%s\n", rcvmsgbuf.data);

           exit(0);

      }

     

      exit(0);

}
相关阅读 更多 +
排行榜 更多 +
虚拟战警

虚拟战警

飞行射击 下载
反恐射击英雄最新版

反恐射击英雄最新版

飞行射击 下载
坦克交火

坦克交火

飞行射击 下载