linux进程通信
管道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | int main(){ int pid; int fd[2]; if (pipe(fd)<0){ //父进程创建管道 perror ( "Fail to pipe" ); exit (EXIT_FAILURE); } if ((pid=fork())<0){ perror ( "Fail to fork" ); exit (EXIT_FAILURE); } else if (pid == 0){ close(fd[1]); //表示管道的方向,fd[1]用于写 child_read_pipe(fd[0]); //子进程读取管道 } else { close(fd[0]); //fd[0]用于读 father_write_pipe(fd[1]); //父进程写入管道 } } |
有名管道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #define FIFO_FILE "MYFIFO" //有名管道server端 int main( void ) { FILE *fp; char readbuf[80]; /* Create the FIFO if it does not exist */ umask(0); mknod(FIFO_FILE, S_IFIFO|0666, 0); while (1) { fp = fopen (FIFO_FILE, "r" ); fgets (readbuf, 80, fp); printf ( "Received string: %s\n" , readbuf); fclose (fp); } return (0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //有名管道client端 int main( int argc, char *argv[]) { FILE *fp; if ( argc != 2 ) { printf ( "USAGE: fifoclient [string]\n" ); exit (1); } if ((fp = fopen (FIFO_FILE, "w" )) == NULL) { perror ( "fopen" ); exit (1); } fputs (argv[1], fp); fclose (fp); return (0); } |
信号
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
typedef struct { int si_signo; int si_errno; int si_code; union sigval si_value; } siginfo_t; union sigval { int sival_int; void *sival_ptr; }
void ouch(int sig) { printf("\nOUCH! - I got signal %d\n", sig); }int main()
{
struct sigaction act;
act.sa_handler = ouch;
//创建空的信号屏蔽字,即不屏蔽任何信息
sigemptyset(&act.sa_mask);
//使sigaction函数重置为默认行为
act.sa_flags = SA_RESETHAND;sigaction(SIGINT, </span>&act, <span style="color: #800080;">0</span><span style="color: #000000;">); </span><span style="color: #0000ff;">while</span>(<span style="color: #800080;">1</span><span style="color: #000000;">) { printf(</span><span style="color: #800000;">"</span><span style="color: #800000;">Hello World!\n</span><span style="color: #800000;">"</span><span style="color: #000000;">); sleep(</span><span style="color: #800080;">1</span><span style="color: #000000;">); } </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span><span style="color: #000000;">;
}
static int alarm_fired = 0;void ouch(int sig)
{
alarm_fired = 1;
}int main()
{
//关联信号处理函数
signal(SIGALRM, ouch);
//调用alarm函数,5秒后发送信号SIGALRM
alarm(5);
//挂起进程
pause();
//接收到信号后,恢复正常执行
if(alarm_fired == 1)
printf("Receive a signal %d\n", SIGALRM);
exit(0);}
消息队列
struct msgbuf { long mtype; /* type of message */ char mtext[1]; /* message text */ };
/* one msqid structure for each queue on the system */ struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /* first message on queue */ struct msg *msg_last; /* last message in queue */ time_t msg_stime; /* last msgsnd time */ time_t msg_rtime; /* last msgrcv time */ time_t msg_ctime; /* last change time */ struct wait_queue *wwait; struct wait_queue *rwait; ushort msg_cbytes; ushort msg_qnum; ushort msg_qbytes; /* max number of bytes on queue */ ushort msg_lspid; /* pid of last msgsnd */ ushort msg_lrpid; /* last receive pid */ };
struct msg_st { long int msg_type; char text[BUFSIZ]; };int main()
{
int running = 1;
int msgid = -1;
struct msg_st data;
long int msgtype = 0; //注意1</span><span style="color: #008000;">//</span><span style="color: #008000;">建立消息队列</span> msgid = msgget((key_t)<span style="color: #800080;">1234</span>, <span style="color: #800080;">0666</span> |<span style="color: #000000;"> IPC_CREAT); </span><span style="color: #0000ff;">if</span>(msgid == -<span style="color: #800080;">1</span><span style="color: #000000;">) { fprintf(stderr, </span><span style="color: #800000;">"</span><span style="color: #800000;">msgget failed with error: %d\n</span><span style="color: #800000;">"</span><span style="color: #000000;">, errno); exit(EXIT_FAILURE); } </span><span style="color: #008000;">//</span><span style="color: #008000;">从队列中获取消息,直到遇到end消息为止</span> <span style="color: #0000ff;">while</span><span style="color: #000000;">(running) { </span><span style="color: #0000ff;">if</span>(msgrcv(msgid, (<span style="color: #0000ff;">void</span>*)&data, BUFSIZ, msgtype, <span style="color: #800080;">0</span>) == -<span style="color: #800080;">1</span><span style="color: #000000;">) { fprintf(stderr, </span><span style="color: #800000;">"</span><span style="color: #800000;">msgrcv failed with errno: %d\n</span><span style="color: #800000;">"</span><span style="color: #000000;">, errno); exit(EXIT_FAILURE); } printf(</span><span style="color: #800000;">"</span><span style="color: #800000;">You wrote: %s\n</span><span style="color: #800000;">"</span><span style="color: #000000;">,data.text); </span><span style="color: #008000;">//</span><span style="color: #008000;">遇到end结束</span> <span style="color: #0000ff;">if</span>(strncmp(data.text, <span style="color: #800000;">"</span><span style="color: #800000;">end</span><span style="color: #800000;">"</span>, <span style="color: #800080;">3</span>) == <span style="color: #800080;">0</span><span style="color: #000000;">) running </span>= <span style="color: #800080;">0</span><span style="color: #000000;">; } </span><span style="color: #008000;">//</span><span style="color: #008000;">删除消息队列</span> <span style="color: #0000ff;">if</span>(msgctl(msgid, IPC_RMID, <span style="color: #800080;">0</span>) == -<span style="color: #800080;">1</span><span style="color: #000000;">) { fprintf(stderr, </span><span style="color: #800000;">"</span><span style="color: #800000;">msgctl(IPC_RMID) failed\n</span><span style="color: #800000;">"</span><span style="color: #000000;">); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS);
}
#define MAX_TEXT 512 struct msg_st { long int msg_type; char text[MAX_TEXT]; };int main()
{
int running = 1;
struct msg_st data;
char buffer[BUFSIZ];
int msgid = -1;</span><span style="color: #008000;">//</span><span style="color: #008000;">建立消息队列</span> msgid = msgget((key_t)<span style="color: #800080;">1234</span>, <span style="color: #800080;">0666</span> |<span style="color: #000000;"> IPC_CREAT); </span><span style="color: #0000ff;">if</span>(msgid == -<span style="color: #800080;">1</span><span style="color: #000000;">) { fprintf(stderr, </span><span style="color: #800000;">"</span><span style="color: #800000;">msgget failed with error: %d\n</span><span style="color: #800000;">"</span><span style="color: #000000;">, errno); exit(EXIT_FAILURE); } </span><span style="color: #008000;">//</span><span style="color: #008000;">向消息队列中写消息,直到写入end</span> <span style="color: #0000ff;">while</span><span style="color: #000000;">(running) { </span><span style="color: #008000;">//</span><span style="color: #008000;">输入数据</span> printf(<span style="color: #800000;">"</span><span style="color: #800000;">Enter some text: </span><span style="color: #800000;">"</span><span style="color: #000000;">); fgets(buffer, BUFSIZ, stdin); data.msg_type </span>= <span style="color: #800080;">1</span>; <span style="color: #008000;">//</span><span style="color: #008000;">注意2</span>
strcpy(data.text, buffer);
//向队列发送数据
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
//输入end结束输入
if(strncmp(buffer, "end", 3) == 0)
running = 0;
sleep(1);
}
exit(EXIT_SUCCESS);
}
共享内存
int main() { int running = 1;//程序是否继续运行的标志 void *shm = NULL;//分配的共享内存的原始首地址 struct shared_use_st *shared;//指向shm int shmid;//共享内存标识符 //创建共享内存 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } //将共享内存连接到当前进程的地址空间 shm = shmat(shmid, 0, 0); if(shm == (void*)-1) { fprintf(stderr, "shmat failed\n"); exit(EXIT_FAILURE); } printf("\nMemory attached at %X\n", (int)shm); //设置共享内存 shared = (struct shared_use_st*)shm; shared->written = 0; while(running)//读取共享内存中的数据 { //没有进程向共享内存定数据有数据可读取 if(shared->written != 0) { printf("You wrote: %s", shared->text); sleep(rand() % 3); //读取完数据,设置written使共享内存段可写 shared->written = 0; //输入了end,退出循环(程序) if(strncmp(shared->text, "end", 3) == 0) running = 0; } else//有其他进程在写数据,不能读取数据 sleep(1); } //把共享内存从当前进程中分离 if(shmdt(shm) == -1) { fprintf(stderr, "shmdt failed\n"); exit(EXIT_FAILURE); } //删除共享内存 if(shmctl(shmid, IPC_RMID, 0) == -1) { fprintf(stderr, "shmctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
int main() { int running = 1; void *shm = NULL; struct shared_use_st *shared = NULL; char buffer[BUFSIZ + 1];//用于保存输入的文本 int shmid; //创建共享内存 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } //将共享内存连接到当前进程的地址空间 shm = shmat(shmid, (void*)0, 0); if(shm == (void*)-1) { fprintf(stderr, "shmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %X\n", (int)shm); //设置共享内存 shared = (struct shared_use_st*)shm; while(running)//向共享内存中写数据 { //数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本 while(shared->written == 1) { sleep(1); printf("Waiting...\n"); } //向共享内存中写入数据 printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); strncpy(shared->text, buffer, TEXT_SZ); //写完数据,设置written使共享内存段可读 shared->written = 1; //输入了end,退出循环(程序) if(strncmp(buffer, "end", 3) == 0) running = 0; } //把共享内存从当前进程中分离 if(shmdt(shm) == -1) { fprintf(stderr, "shmdt failed\n"); exit(EXIT_FAILURE); } sleep(2); exit(EXIT_SUCCESS); }
信号量
struct sembuf{ short sem_num;//除非使用一组信号量,否则它为0 short sem_op;//信号量在一次操作中需要改变的数据,-1,即P(等待)操作+1,即V(发送信号)操作,0表示sleep直到信号量的值为0,即资源得到百分百利用。 short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,并在进程没有释放该信号量而终止时,操作系统释放信号量;IPC_NOWAIT得不到资源立刻返回。 };
/* arg for semctl system calls. */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ ushort *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ void *__pad; };
int main(int argc, char *argv[]) { char message = 'X'; int i = 0; //创建信号量 sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT); if(argc > 1) { //程序第一次被调用,初始化信号量 if(!set_semvalue()) { fprintf(stderr, "Failed to initialize semaphore\n"); exit(EXIT_FAILURE); } //设置要输出到屏幕中的信息,即其参数的第一个字符 message = argv[1][0]; sleep(2); } for(i = 0; i < 10; ++i) { //进入临界区 if(!semaphore_p()) exit(EXIT_FAILURE); //向屏幕中输出数据 printf("%c", message); //清理缓冲区,然后休眠随机时间 fflush(stdout); sleep(rand() % 3); //离开临界区前再一次向屏幕输出数据 printf("%c", message); fflush(stdout); //离开临界区,休眠随机时间后继续循环 if(!semaphore_v()) exit(EXIT_FAILURE); sleep(rand() % 2); } sleep(10); printf("\n%d - finished\n", getpid()); if(argc > 1) { //如果程序是第一次被调用,则在退出前删除信号量 sleep(3); del_semvalue(); } exit(EXIT_SUCCESS); } static int set_semvalue() { //用于初始化信号量,在使用信号量前必须这样做 union semun sem_union; sem_union.val = 1; if(semctl(sem_id, 0, SETVAL, sem_union) == -1) return 0; return 1; } static void del_semvalue() { //删除信号量 union semun sem_union; if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) fprintf(stderr, "Failed to delete semaphore\n"); } static int semaphore_p() { //对信号量做减1操作,即等待P(sv) struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = -1;//P() sem_b.sem_flg = SEM_UNDO; if(semop(sem_id, &sem_b, 1) == -1) { fprintf(stderr, "semaphore_p failed\n"); return 0; } return 1; } static int semaphore_v() { //这是一个释放操作,它使信号量变为可用,即发送信号V(sv) struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1;//V() sem_b.sem_flg = SEM_UNDO; if(semop(sem_id, &sem_b, 1) == -1) { fprintf(stderr, "semaphore_v failed\n"); return 0; } return 1; }