消息队列/共享内存方法

时间:2014-04-02 03:15:02

标签: linux

我在使用下面的IPC(进程间通信)程序时遇到了一些问题。 请让我解释一下: 我想传递Linux命令,如“ls”或“wc file.txt” 从父级到子级,使用消息队列执行,和 然后让孩子将命令输出返回给 父进程使用共享内存方法。

但这就是我得到的:父进程总是让输出落后一步; 以下列方式:

Step1)ls file.txt (什么都没出现。)

Step2)wc file.txt (早先的命令“ls file.txt”的输出显示在这里。)

步骤3)cat file.txt (早先的命令“wc file.txt”的输出显示了。)

感谢任何帮助。

编译:gcc -o program ./program.c
运行:-./program -v

代码:

#define BUFSZ 512
#define ERRBUFSZ 512
#define TIMEOUT_TIMEDIO 20
#define SHM_SIZE       5120 
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>    
#include <setjmp.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

static sigjmp_buf jmpbuf;

int timed_io(char* buf, int len, FILE* rfp, int sec);
static void sigalrm_handler(int signo);
void do_cmd(char *buf, int len, int linenum, char *errbuf);
int parse_cmd(char *buf, char **vbuf, char *errbuf);
int process_cmd_ipc(char *argv, int linenum, char *errbuf);

struct my_msgbuf {
long mtype;
char mtext[256];
};

static void sigalrm_handler(int signo)
{
   siglongjmp(jmpbuf, 1);
}

int timed_io(char* buf, int len, FILE* rfp, int sec)
{
   struct sigaction nsigaction[1];
   struct sigaction osigaction[1];

   int prev_alrm;
   int st = 0; 

if(sigsetjmp(jmpbuf, 1) == 0)
{
nsigaction->sa_handler = sigalrm_handler;
sigemptyset(&nsigaction->sa_mask);
nsigaction->sa_flags = SA_RESTART;

prev_alrm = alarm(0);
sigaction(SIGALRM, nsigaction, osigaction);

alarm(sec);

if (fgets(buf, len, rfp) == NULL)
        st = -1; // EOF

buf[strlen(buf) - 1] = 0;
   }
   else { st = -2; }       // Time-out

   alarm(0);    // Reset old alarm and handler
   sigaction(SIGALRM, osigaction, 0);
   return st;
}

int process_cmd_ipc(char *argv, int linenum, char* errbuf) 
{
   struct my_msgbuf buf;
   int msqid, msqid_parent, st, shmid, str_len;
   key_t key, key_shm;
   char* shared_buf;
   FILE *fd;

   // create key for shared memory segment
   if ((key_shm = ftok("shm_key.txt", 'R')) == -1) {
      perror("ftok");
      exit(1);
   }

   // Connect to shared memory segment 
   if ((shmid = shmget(key_shm, SHM_SIZE, 0644 | IPC_CREAT)) == -1)
   {
      perror("shmget");
      exit(1);
   }

   // Attach to shared memory segment
   shared_buf = shmat(shmid, (void *) 0, 0);
   if (shared_buf == (char *) (-1)) {
      perror("shmat");
      exit(1);
   }
   // End of shared memory section` //

   // Begin: message queue section
   pid_t   cpid=fork();
   if (cpid<0) {
      fprintf(stderr,"ERR: \"fork\" error! (Line=%d)\n", linenum); 
      exit (-1);
   } else if (cpid==0)      // child process
   {  // Begin: message queue 
      if ((key = ftok("mysh.c", 'B')) == -1) {
      perror("ftok");
      exit(1);
   }

   if ((msqid = msgget(key, 0644)) == -1) {
      perror("msgget from child");
      exit(1);
   }

   memset(buf.mtext, 0, sizeof(buf.mtext));    // Clear buffer

   if(msgrcv(msqid, (struct msgbuf*) &buf, sizeof(buf), 0,0) == -1)
   {
      perror("msgrcv");
      exit(1);
   }
   // End: message queue

   // begin: shared memory segment 
   memset(shared_buf, 0, SHM_SIZE);   // zeroize shared_buf
   fd = popen(buf.mtext, "r");

   str_len = 0;
   while(fgets(shared_buf + str_len, SHM_SIZE, fd) != NULL)
   { str_len = strlen(shared_buf); }

   pclose(fd);
   // end: shared memory segment 
}
else { // parent 
  // Begin - message queue
  if ((key = ftok("mysh.c", 'B')) == -1) {
     perror("ftok");
     exit(1);
  }

  if ((msqid_parent = msgget(key, 0644 | IPC_CREAT)) == -1) {
     perror("msgget from parent");
     exit(1);
  }

  buf.mtype = 1;
  strncpy(buf.mtext, argv, strlen(argv));

  if(msgsnd(msqid_parent, (struct my_msgbuf*) &buf, strlen(buf.mtext), 0) == -1)
     perror("msgsnd");
    // End - message queue

    // Begin - shared memory
    // usleep(10000);
    printf("%s", shared_buf);
    // End - shared memory 
   } // if-else fork
}  

int parse_cmd(char *buf, char **vbuf, char *errbuf) 
{
   int i=0;
   char *delim=" ,\t\n";
   char *tok;

   tok=strtok(buf,delim);

   while (tok) {
      vbuf[i]=(char *)malloc(BUFSZ*sizeof(char));
      strcpy(vbuf[i],tok);
      tok=strtok(NULL,delim);
      i++;
   }

   vbuf[i]=0;
   return i;
}

void do_cmd(char *buf, int len, int linenum, char *errbuf) {
   int i=0; int numargs;
   char *vbuf[128];   

   char* copy = (char *) malloc(strlen(buf) + 1);
   int maxargs=sizeof(vbuf)/sizeof(char *);

   strcpy(copy, buf);
   numargs = parse_cmd(copy,vbuf,errbuf);
   process_cmd_ipc(buf,linenum, errbuf);

   for (i=0;i<numargs; i++) { free(vbuf[i]); }
   free(copy);
   copy = NULL;

   return;
}

int main(int argc, char **argv) 
{
   int i; int st; int linenum=0;
   char *buf=(char *)malloc(BUFSZ*sizeof(char)); 
   char *errbuf=(char *)malloc(ERRBUFSZ*sizeof(char)); 
   char *mysh = "";
   FILE *rfp=stdin;

   if (isatty(fileno(rfp))) {
      mysh = "mysh (Ctrl-C to exit)>";
      fprintf(stderr,"%s",mysh);
   }

   while(1)
   {
      st = timed_io(buf, BUFSZ, stdin, TIMEOUT_TIMEDIO);
      if (st != 0)
      {
         fprintf(stderr, "ERR: No input %s (Status=%d)\n", errbuf, st);
         return -1;
      }
      else
      {
         linenum++;

         if (*buf)
         {  do_cmd(buf, BUFSZ, linenum,errbuf); }

         if (mysh) 
            fprintf(stderr,"%s",mysh);
      }
   }
}

0 个答案:

没有答案