巴州网站建设,免费网站免费在线观看,有没有做丝网的网站呀,wordpress分类不同模板进程间通信#xff1a;采用IPC机制#xff08;进程间的用户空间相互独立#xff0c;内核空间共享#xff09;#xff0c;有管道#xff0c;信号量#xff0c;共享内存#xff0c;消息队列#xff0c;套接字。
一.管道 管道可以用来在两个进程之间传递数据#xff0c…进程间通信采用IPC机制进程间的用户空间相互独立内核空间共享有管道信号量共享内存消息队列套接字。
一.管道 管道可以用来在两个进程之间传递数据如 ps -ef | grep “bash”, 其中‘|’就是管 道其作用就是将 ps 命令的结果写入管道文件然后 grep 再从管道文件中读出该数据进行 过滤。 1.1有名管道 有名管道可以在任意两个进程之间通信 有名管道的创建 ◼ 命令创建 mkfifo FIFO ◼ 系统调用创建 #include sys/types.h #include sys/stat.h //filename 是管道名 mode 是创建的文件访问权限 int mkfifo(const char *filename, mode_t mode); a.c代码 #includestdio.h
#includestdlib.h
#includeunistd.h
#includestring.h
#includefcntl.hint main()
{int fd open(./fifo,O_WRONLY);if(fd -1){exit(1);}printf(fd%d\n,fd);while(1){printf(intput:\n);char buff[128] {0};fgets(buff,128,stdin);if(strncmp(buff,end,3) 0){break;}write(fd,buff,strlen(buff));}close(fd);
} b.c代码 #includestdio.h
#includestdlib.h
#includeunistd.h
#includestring.h
#includefcntl.hint main()
{int fd open(./fifo,O_RDONLY);printf(fd%d\n,fd);if(fd -1){exit(1);}while(1){char buff[128];int nread(fd,buff,127);if(n0){break;}printf(buff%s\n,buff);}close(0);exit(0);
} 运行 1.2无名管道 无名管道主要应用于父子进程间的通信。 无名管道的创建 1. #include unistd.h 2. /* 3. pipe()成功返回 0失败返回-1 4. fds[0]是管道读端的描述符 5. fds[1]是管道写端的描述符 6. */ 7. int pipe(int fds[2]); #includestdio.h
#includestring.h
#includeunistd.h
#includestdlib.h
//无名管到
int main()
{int fd[2];//fd[0] r fd[1] wif(pipe(fd) -1){exit(1);}write(fd[1],hello,5);char buff[128] {0};read(fd[0],buff,127);printf(%s\n,buff);close(fd[0]);close(fd[1]);exit(0);
}无名管道父子进程间的通信 #includestdio.h
#includestring.h
#includeunistd.h
#includestdlib.hint main()
{int fd[2];//fd[0] r fd[1] wif(pipe(fd) -1){exit(1);}pid_t pid fork();if(pid -1){exit(1);}if(pid0){close(fd[1]);while(1){char buff[128]{0};//read(fd[0],buff,127);if(read(fd[0],buff,127) 0){//printf(child read:%s\n,buff);break;}printf(chlid read:%s\n,buff);}close(fd[0]);}else{close(fd[0]);while(1){printf(input: );char buff[128] {0};fgets(buff,128,stdin);if(strncmp(buff,end,3)0){break;}write(fd[1],buff,strlen(buff));}close(fd[1]);}exit(0);
} 1.3管道的特点 ◼ 无论有名还是无名写入管道的数据都在内存中 ◼ 管道是一种半双工通信方式通信方式有单工、半双工、全双工 ◼ 有名和无名管道的区别有名可以在任意进程间使用而无名主要在父子进程间 1.4管道的实现 二.信号量 由于父子进程间无法确定谁先谁后所以运行结果会有顺序错乱的情况 提出使用信号量管理使得父子进程间的通信变得有序 1.信号量 信号量是一个特殊的变量一般取正数值。它的值代表允许访问的资源数目获取资源 时需要对信号量的值进行原子减一该操作被称为 P 操作。当信号量值为 0 时代表没有 资源可用P 操作会阻塞。释放资源时需要对信号量的值进行原子加一该操作被称为 V 操作。信号量主要用来同步进程。信号量的值如果只取 0,1将其称为二值信号量。如果信 号量的值大于 1则称之为计数信号量。 临界资源同一时刻只允许被一个进程或线程访问的资源 临界区访问临界资源的代码段 2.信号量的使用 操作信号量的接口介绍 #include sys/sem.h#include sys/types.h#include sys/ipc.h/*semget()创建或者获取已存在的信号量semget()成功返回信号量的 ID 失败返回-1key两个进程使用相同的 key 值就可以使用同一个信号量nsems内核维护的是一个信号量集在新建信号量时其指定信号量集中信号
量的个数semflg 可选 IPC_CREAT IPC_EXCL*/int semget(key_t key, int nsems, int semflg);/*semop()对信号量进行改变做 P 操作或者 V 操作semop()成功返回 0失败返回-1struct sembuf{unsigned short sem_num; //指定信号量集中的信号量下标short sem_op; //其值为-1代表 P 操作其值为 1代表 V 操作short sem_flg; //SEM_UNDO};*/int semop(int semid, struct sembuf *sops, unsigned nsops);/*semctl()控制信号量semctl()成功返回 0失败返回-1cmd 选项 SETVAL IPC_RMIDunion semun{int val;
struct semid_ds *buf;unsigned short *array;struct seminfo *_buf;};*/
int semctl(int semid, int semnum, int cmd, ...); 例题进程 a 和进程 b 模拟访问打印机进程 a 输出第一个字符‘a’表示开始使用打印 机输出第二个字符‘a’表示结束使用b 进程操作与 a 进程相同。由于打印机同一时刻 只能被一个进程使用所以输出结果不应该出现 abab如图所示 封装信号量的接口 sem.h 的代码如下 #includestdio.h
#includestring.h
#includeunistd.h
#includestdlib.h
#includesys/sem.hunion semun
{int val;
};
void sem_init();
void sem_p();
void sem_v();
void sem_destroy();sem.c 的代码如下 #include sem.hstatic int semid -1;
void sem_init()
{semid semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);if(semid -1){semid semget((key_t)1234,1,IPC_CREAT|0600);//创建失败说明已有获取if(semid -1){printf(semget err\n);return;}}else//创建成功初始化{union semun a;a.val 1;if(semctl(semid,0,SETVAL,a) -1){printf(semcrl setval err\n);}}
}
void sem_p()
{struct sembuf buf;buf.sem_num 0; //信号两的下标目前只有一个下标为0buf.sem_op -1;//pbuf.sem_flg SEM_UNDO;if(semop(semid,buf,1) -1){printf(semop p err\n);}
}
void sem_v()
{struct sembuf buf;buf.sem_num 0; //信号两的下标目前只有一个下标为0buf.sem_op 1;//vbuf.sem_flg SEM_UNDO;if(semop(semid,buf,1) -1){printf(semop v err\n);}
}
void sem_destroy()//销毁信号量
{if(semctl(semid,0,IPC_RMID) -1){printf(semctl destroy err\n);}
} a.c 的代码如下 #includestdio.h
#includestring.h
#includeunistd.h
#includestdlib.h
#includesys/sem.h
#includesem.h
int main()
{sem_init();for(int i 0;i5;i){sem_p();printf(A);fflush(stdout);int n rand() %3;sleep(n);printf(A);fflush(stdout);;sem_v();nrand() %3;sleep(n);}
}
//gcc -o a a.c sem.c
//gcc -o b b.c sem.c b.c代码 #includestdio.h
#includestring.h
#includeunistd.h
#includestdlib.h
#includesys/sem.h
#includesem.h
int main()
{sem_init();for(int i 0;i5;i){sem_p();printf(B);fflush(stdout);int n rand() %3;sleep(n);printf(B);fflush(stdout);sem_v();nrand() %3;sleep(n);}sleep(10);sem_destroy();
} 运行结果如下图所示输出结果只截了部分 练习题: 三个进程 a、b、c 分别输入“A”、“B”、“C”要求输出结果必须是“ABCABCABC…” 3.ipcs/ipcrm 介绍 ipcs 可以查看消息队列、共享内存、信号量的使用情况使用 ipcrm 可以进行删除操作。