管道通信相关资料 linux系统调用

来源:互联网 发布:glanceplus软件翻译 编辑:程序博客网 时间:2024/05/19 08:39

实验参考:LINUX系统调用

1. 进程控制的系统调用

l fork系统调用创建新的子进程

格式: pid=int fork()

fork调用返回时,系统中已有两个用户级环境完全相同的进程存在,这两个

进程从fork调用中得到的返回值不同,其中子进程得到的返回值为零,父进程

得到的返回值是新创建子进程的进程标识号。

l exec系统调用

格式:(六种)

int execl(path,arg0,arg1,…,argn,(char *)0)

char *path, *arg0, *arg1, …, *argn ;

exec调用进程的正文段被指定的目标文件的正文段所覆盖,其属性的变化方

式与fork成功后从父进程那里继承属性的方式几乎是一样的。系统中绝大多数

命令都是通过exec来执行的,不但shell进程所创建的子进程使用它来执行用户

命令,shell进程本身和它的祖先进程也是用exec来启动执行的。

l exit 系统调用终止进程执行

格式:void exit(status)

int status ;

参数status是调用进程终止时传递给其父进程的值。如调用进程还有子进

程,则将其所有子进程的父进程改为1号进程。

l wait 系统调用等待子进程暂仃或终止

格式:int wait(stat_loc) int wait((int *)0)

int stat_loc ;

wait 调用将调用进程挂起,直到该进程收到一个被其捕获的信号或者它的任

何一个子进程暂仃或终止为止。如果wait 调用之前已有子进程暂仃或终止,则

该调用立即返回。

l lockf 锁定文件

格式:int lockf(fd,fuction,size)

int files, fuction; long size; fd – 锁定文件标识

function=0不锁定表示

=1锁定

=2测试和锁定

=3测试有否被锁定

size --锁定或解锁的字节数,0表示从文件的当前位置到文件尾。

 

程序实例:

#include <stdio.h>

void main(intargc, char *argv[ ])

{ int pid;

pid=fork(); /*fork child process */

if (pid<0){fprintf(stderr, “Fork Failed”); exit(-1);

}

else if (pid==0){ execlp(“/bin/ls”,”ls”,NULL);

} /* childprocess */

else {wait(NULL);

printf(“child Complete”);

exit(0);

} /*parentprocess */

}

2.进程通信的管道方式

l  pipe系统调用

格式: intpipe (filedes)

int filedes [2];

 

程序实例:管道通信

#include <stdio.h>

#include <fcntl.h>

char parent[]={“A message from parent .”};

char child[]={“A message from child .”};

main()

{int chan1[2],chan2[2];

char buf[100];

if (pipe(chan1)==-1 || pipe(chan2)==-1) errexit(“pipe”);

if (fork())

{close(chan1[0]); close(chan2[1]);

write(chan1[1],parent,sizeof parent);

close(chan1[1]);

read(chan2[0],buf,100);

printf(“parent process : %s \n”,buf);

close(chan2[0]);

}

else

{close(chan1[1]); close(chan2[0]);

read(chan1[0],buf,100);

printf(“child process : %s \n”,buf);

write(chan2[1],child,sizeof child);

close(chan2[1]); close(chan1[0]);

}

}

 

3.进程通信的消息队列方式

 

消息队列就是消息的一个链表,它允许一个或多个进程向它写消息,一个或多个进程从中读消息。具有一定的FIFO的特性,但是可实现消息的随即查询。这些消息存在于内核中,由“队列ID”来标识。

消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。

msgget:创建和打开队列,其消息数量受系统限制。

msgsnd:添加消息,将消息添加到消息队列尾部。

msgrcv:读取消息,从消息队列中取走消息。

msgctl:控制消息队列。

int msgget (key_tkey, int flag) 

   key:返回新的或已有队列的ID,IPC_PRIVATE

int msgsnd (intmsqid, struct msgbuf  *msgp, size_t msgsz, int flag)

  其中:msqid是消息队列的队列ID;msgp是消息内容所在的缓冲区;msgsz是消息的大小;msgflg是标志,IPC_NOWAIT若消息并没有立即发送而调用进程会立即返回。

int msgrcv (intmsqid, struct  msgbuf *msgp, size_t msgsz,long  msgtyp, int flag)

msqid是消息队列的引用标识符;msgp是接收到的消息将要存放的缓冲区;msgsz是消息的大小;msgtyp是期望接收的消息类型;

int msgctl (intmsqid, int cmd, struct msqid_ds *buf)

 msqid是消息队列的引用标识符;cmd是执行命令;buf是一个缓冲区。cmd参数指定对于由msqid规定的队列要执行的命令:IPC_STAT 取此队列的msqid_ds结构,并将其存放在buf指向的结构中。IPC_SET 按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。

IPC_RMID 从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回 EIDRM。

此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。msgflg是标志。

 

程序实例:

1)mesg_que_send.c

intmain()

{   

key_tkey;

intmsgkey;

pid_tpid;

intcount=0;

structmsgbuf{

       int mtype;

       pid_t from;

       int count;

       char mtext[50];

    }wmsg;

 key=ftok("/home/yandongsheng/",10);

 pid=getpid();//获得发送进程的id

 if((msgkey=msgget(key,IPC_CREAT|0660))<0)

     {

            fprintf(stderr,"msgget error%s\n",strerror(errno));

            exit(1);

        }

 printf("msgget key %d\n",msgkey);

fflush(stdout);

 while(1)

 {

   count++;

   bzero(&wmsg,sizeof(wmsg));

   wmsg.mtype=10; //消息的类型

    wmsg.count=count;

    wmsg.from=pid;

    strcpy(wmsg.mtext,"hello,i amcoming");

    if(msgsnd(msgkey,&wmsg,sizeof(wmsg.mtext),MSG_NOERROR)<0)

     {

            fprintf(stderr,"msgsnd error%s\n",strerror(errno));

        }

      sleep(2);

     }

     if((msgctl(msgkey,IPC_RMID,NULL))<0){

          perror("msgctl");

    exit(1);

    }

return0;

}

   

 

2)mesg_que_recv.c

 

intmain()

{   

    key_t key;

    pid_t pid;

    int msgkey;

    struct msgbuf{

       int mtype;

       pid_t from;

       int count;

       char mtext[50];

    }rmsg;//消息的格式应该是一样的

    pid=getpid();

   key=ftok("/home/yandongsheng/",10);

    while(1)

    {     

      bzero(&rmsg,sizeof(rmsg));

     if(msgrcv(msgkey,&rmsg,sizeof(rmsg.mtext),0,MSG_NOERROR)<0)

       {

        perror("msgrcv error");

       }

       printf("rmsg.from=%d\nmy pidis:",rmsg.from,pid);

       printf("rmsg.mtype=%d\nrmsg.count=%d\nrmsg.mtext=%s\n",rmsg.mtype,rmsg.count,rmsg.mtext);

      sleep(2);

    }

    if((msgctl(msgkey,IPC_RMID,NULL))<0){

          perror("msgctl");

    exit(1);

    }

return0;

}

 

 

先运行mesg_que_send.c 后运行mesg_que_recv.c 仅做演示

 

0 0
原创粉丝点击