Written on 8:39 下午 by Yu Lai
From: http://blog.csdn.net/lcrystal623/archive/2007/03/16/1531201.aspx
具名管線可以用於任何兩個程序間通信,因為有名字可引用。注意管道都是單向的,因此雙方通信需要兩個管道。
下面分別是這兩個程式代碼,同樣是Lucy先運行,然後是Peter。
fifoLucy.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
char write_fifo_name[] = "lucy";
char read_fifo_name[] = "peter";
int write_fd, read_fd;
char buf[256];
int len;
struct stat stat_buf;
int ret = mkfifo(write_fifo_name, S_IRUSR | S_IWUSR);
if( ret == -1)
{
printf("Fail to create FIFO %s: %s",write_fifo_name,strerror(errno));
exit(-1);
}
write_fd = open(write_fifo_name, O_WRONLY);
if(write_fd == -1)
{
printf("Fail to open FIFO %s: %s",write_fifo_name,strerror(errno));
exit(-1);
}
while((read_fd = open(read_fifo_name,O_RDONLY)) == -1)
{
sleep(1);
}
while(1)
{
printf("Lucy: ");
fgets(buf, 256, stdin);
buf[strlen(buf)-1] = '\0';
if(strncmp(buf,"quit", 4) == 0)
{
close(write_fd);
unlink(write_fifo_name);
close(read_fd);
exit(0);
}
write(write_fd, buf, strlen(buf));
len = read(read_fd, buf, 256);
if( len > 0)
{
buf[len] = '\0';
printf("Peter: %s\n", buf);
}
}
}
fifoPeter.c
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
int main(void)
{
char write_fifo_name[] = "peter";
char read_fifo_name[] = "lucy";
int write_fd, read_fd;
char buf[256];
int len;
int ret = mkfifo(write_fifo_name, S_IRUSR | S_IWUSR);
if( ret == -1)
{
printf("Fail to create FIFO %s: %s",write_fifo_name,strerror(errno));
exit(-1);
}
while((read_fd = open(read_fifo_name, O_RDONLY)) == -1)
{
sleep(1);
}
write_fd = open(write_fifo_name, O_WRONLY);
if(write_fd == -1)
{
printf("Fail to open FIFO %s: %s", write_fifo_name, strerror(errno));
exit(-1);
}
while(1)
{
len = read(read_fd, buf, 256);
if(len > 0)
{
buf[len] = '\0';
printf("Lucy: %s\n",buf);
}
printf("Peter: ");
fgets(buf, 256, stdin);
buf[strlen(buf)-1] = '\0';
if(strncmp(buf,"quit", 4) == 0)
{
close(write_fd);
unlink(write_fifo_name);
close(read_fd);
exit(0);
}
write(write_fd, buf, strlen(buf));
}
}
Posted in
技術,
IPC,
Linux
|
Written on 8:36 下午 by Yu Lai
From: http://blog.csdn.net/lcrystal623/archive/2007/03/16/1531189.aspx
多程序實現PV操作,子程序為生產者,倉庫可以容納5個物品,每次檢查倉庫是否滿,若不滿則執行P操作,生產一個物品放入倉庫。父程序檢驗倉庫是否空,若不空則消耗一個物品,執行V操作。sleep函數是隨即設置生產或消費所用時間。
程式主要目的是展示Semaphores的使用,以備以後參考。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
int main()
{
int semID,ret,num;
int sleepTime;
struct sembuf buf;
semID = semget(IPC_PRIVATE,1,0666);
if(semID < 0)
{
printf("建立Semaphores出錯\n");
exit(1);
}
if(fork() == 0)
{
while(1)
{
num = semctl(semID,0,GETVAL,NULL);
if(num < 5)
{
sleepTime = rand() % 5;
sleep(sleepTime);
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = 0;
ret = semop(semID,&buf,1);
if(ret < 0)
{
printf("執行P操作失敗!\n");
exit(1);
}
num = semctl(semID,0,GETVAL,NULL);
printf("生產者生產了一個物品放入了倉庫...倉庫中現有物品%d個\n",num);
}
}
}
else
{
while(1)
{
num = semctl(semID,0,GETVAL,NULL);
if(num > 0)
{
sleepTime = rand() % 5;
sleep(sleepTime);
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = 0;
ret = semop(semID,&buf,1);
if(ret < 0)
{
printf("執行V操作失敗!\n");
exit(1);
}
num = semctl(semID,0,GETVAL,NULL);
printf("消費者從倉庫中消耗了一個物品...倉庫中現有物品%d個\n",num);
}
}
}
return 0;
}
Posted in
技術,
IPC,
Linux
|
Written on 8:23 下午 by Yu Lai
From: http://blog.csdn.net/lcrystal623/archive/2007/03/16/1531183.aspx
檔案msg為空檔案,可以為任何內容,這裡只是為了ftok函數使用。程式透過建立Message Queue,完成程序間通信,注意msgrcv的第四個參數為Message Type,他定義了從Queue中取得Message的Type。
下面是msgLucy.c,是建立Message Queue的
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#define PROJID 0xFF
#define LUCY 1
#define PETER 2
int mqid;
void terminate_handler(int signo)
{
msgctl(mqid,IPC_RMID,NULL);
exit(0);
}
int main()
{
char filenm[] = "msg";
key_t mqkey;
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[256]; /* message data */
}msg;
int ret;
mqkey = ftok(filenm,PROJID);
if(mqkey == -1)
{
perror("ftok error: ");
exit(-1);
}
mqid = msgget(mqkey,IPC_CREAT | IPC_EXCL | 0666);
if(mqid == -1)
{
perror("msgget error: ");
exit(-1);
}
signal(SIGINT, terminate_handler);
signal(SIGTERM, terminate_handler);
while(1)
{
printf("Lucy: ");
fgets(msg.mtext, 256, stdin);
if (strncmp("quit", msg.mtext, 4) == 0)
{
msgctl(mqid,IPC_RMID,NULL);
exit(0);
}
msg.mtext[strlen(msg.mtext)-1] = '\0';
msg.mtype = LUCY;
msgsnd(mqid,&msg,strlen(msg.mtext) + 1,0);
msgrcv(mqid,&msg,256,PETER,0);
printf("Peter: %s\n", msg.mtext);
}
}
下面的是msgPeter,是和Lucy通信的,程式先執行Lucy,再執行Peter
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#define PROJID 0xFF
#define LUCY 1
#define PETER 2
int main()
{
char filenm[] = "msg";
int mqid;
key_t mqkey;
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[256]; /* message data */
}msg;
int ret;
mqkey = ftok(filenm, PROJID);
if(mqkey == -1)
{
perror("ftok error: ");
exit(-1);
}
mqid = msgget(mqkey, 0);
if(mqid == -1)
{
perror("msgget error: ");
exit(-1);
}
while(1)
{
msgrcv(mqid,&msg,256,LUCY,0);
printf("Lucy: %s\n",msg.mtext);
printf("Peter: ");
fgets(msg.mtext,256,stdin);
if(strncmp("quit", msg.mtext, 4) == 0)
{
exit(0);
}
msg.mtext[strlen(msg.mtext)-1] = '\0';
msg.mtype = PETER;
msgsnd(mqid,&msg,strlen(msg.mtext) + 1,0);
}
}
Posted in
技術,
IPC,
Linux
|
Written on 8:07 下午 by Yu Lai
From: http://blog.csdn.net/lcrystal623/archive/2007/03/05/1521168.aspx
管線只能用於父子程序間通信,pipe函式用一個int[]作參數,int[] fd中fd[0]用於讀,fd[1]用於寫。代碼如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
int main()
{
int pipe1_fd[2], pipe2_fd[2];
char * parent_talks[] = {"Hi, my baby","Can you tell daddy date and time?","Daddy have to leave here, bye!",NULL};
char * child_talks[] = {"Hi, daddy","Sure,","Bye!",NULL};
char parent_buf[256], child_buf[256];
char * parent_ptr, * child_ptr;
int i,j, len;
int child_status;
time_t curtime;
if(pipe(pipe1_fd) < 0)
{
printf("pipe1 create error\n");
return -1;
}
if(pipe(pipe2_fd) < 0)
{
printf("pipe2 create error\n");
return -1;
}
if(fork() == 0) //child
{
//pipe1_fd[0] is used to read, pipe2_fd[1] is used to write
close(pipe1_fd[1]);
close(pipe2_fd[0]);
i = 0;
child_ptr = child_talks[i];
while(child_ptr != NULL)
{
len = read(pipe1_fd[0],child_buf,255);
child_buf[len] = '\0';
printf("Parent: %s\n",child_buf);
if(i == 1)
{
time(&curtime);
len = sprintf(child_buf, "%s %s", child_ptr, ctime(&curtime));
child_buf[len-1] = '\0';
write(pipe2_fd[1],child_buf,strlen(child_buf));
}
else
{
write(pipe2_fd[1],child_ptr,strlen(child_ptr));
}
child_ptr = child_talks[++i];
}
close(pipe1_fd[0]);
close(pipe2_fd[1]);
exit(0);
}
else //parent
{
//pipe1_fd[1] is used to write, pipe2_fd[0] is used to read
close(pipe1_fd[0]);
close(pipe2_fd[1]);
j = 0;
parent_ptr = parent_talks[j];
while(parent_ptr != NULL)
{
write(pipe1_fd[1],parent_ptr,strlen(parent_ptr));
len = read(pipe2_fd[0],parent_buf,255);
parent_buf[len] = '\0';
printf("Child: %s\n", parent_buf);
parent_ptr = parent_talks[++j];
}
close(pipe1_fd[1]);
close(pipe2_fd[0]);
wait(&child_status);
exit(0);
}
}
Posted in
技術,
IPC,
Linux
|
Written on 7:40 下午 by Yu Lai
From: http://blog.csdn.net/lcrystal623/archive/2007/03/05/1521158.aspx
要運行程式,需要在當前目錄下建立一個share檔案,share是一個空檔案,沒有任何意義,只是函數ftok需要一個檔案名作參數,ftok另一個參數可以為任何數字。
程式執行後,分為父子程序,子程序申請Shared Memory,然後等待父程序繼續執行,父程序首先等待子程序申請到Shared Memory區段(segment),然後輸出Shared Memory中的內容,為了演示Shared Memory可以隨時更新,程序中在子程序裡產生隨機數寫入Shared Memory供父程序讀取。
代碼如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int shmID;
char * buf;
void finalize(int signo)
{
shmctl(shmID,IPC_RMID,NULL);
exit(0);
}
int main()
{
int i = 1;
key_t shmKey;
signal(SIGINT,finalize);
signal(SIGTERM,finalize);
if(fork() == 0) //子程序
{
shmKey = ftok("share",16); //可以使用任何大於0的數字,如果名字和數相同,則產生的key相同。
if(shmKey == -1)
{
printf("建立key出錯\n");
exit(-1);
}
shmID = shmget(shmKey,20,IPC_CREAT | IPC_EXCL | 0666);
if(shmID == -1)
{
printf("建立Shared Memory Segment出錯\n");
exit(-1);
}
sleep(2); //等待父程序執行,好顯示第一行為空。
while(1)
{
buf = (char *)shmat(shmID,NULL,0);
srandom(time(NULL));
sprintf(buf,"%d",random());
shmdt(buf);
}
}
else //父程序
{
sleep(1); //讓子程序先執行,以建立Shared Memory Segment。
shmKey = ftok("share",16); //可以使用任何大於0的數字,如果名字和數相同,則產生的key相同。
if(shmKey == -1)
{
printf("建立key出錯\n");
exit(-1);
}
shmID = shmget(shmKey,20,0); //0表示如果shmKey映射的不存在則報錯。
if(shmID == -1)
{
printf("引用Segment id出錯\n");
exit(-1);
}
while(1)
{
buf = (char *)shmat(shmID,NULL,0);
printf("%d. 現在Shared Memory中的內容為:%s\n",i++,buf);
shmdt(buf);
sleep(1);
}
}
return 0;
}
Posted in
技術,
IPC,
Linux
|