提交 12ef6ebd 编写于 作者: H hypox64

4-14

上级 ecdfdab1
......@@ -156,7 +156,7 @@ FIFO 任务执
#### 3-27&3-28实时进程负载均衡
进程在八个处理器上运行
![image](./record/pic/3-28.png)
![image](./record/pic/3-27.png)
高优先级实时进程抢占低优先级实时进程的示例,开启一个优先级更高的进程
![image](./record/pic/3-28.png)
......@@ -219,6 +219,7 @@ cat RT-Balance.sh
实际结果(一开始运行就卡炸了):
首先,8个优先级较高的开始运行,最高占用不超过95%
此时可以观察到8个进程所占用的CPU核心会发生跳动
![image](./homework/4/4-1.png)
待8个优先级较高的进程执行完成后,优先级较低的进程开始执行
![image](./homework/4/4-2.png)
\ No newline at end of file
### 4-1 无名管道
* 管道(pipe),或称无名管道,是所有 Unix 都提供的一种进程间通信机制。
* Unix 命令中使用“|”来连接两个命令时使用的就是管道,例如“ls | more”
* 无名管道有一个主要缺点,只能通过父子进程之间(及其后代)使用文件描述符的继承来访问,无法在任意的进程之间使用。
屏显 4-1 pipe-demo 的输出
![image](./record/pic/4-1.png)
### 4-2&4-3&4-4 命名管道(FIFO)
* FIFO 就是无名管道的升级版——有可访问的磁盘索引节点,即 FIFO 文件将出现在目录树中(不像无名管道那样只存在于 pipefs 特殊文件系统中)
4-2 mkfifo 创建命名管道
4-3 用 cat 尝试读取空的管道文件(阻塞)
![image](./record/pic/4-2.png)
4-4 用 echo 向管道写入数据(cat 被唤醒并显示管道文件的内容)
![image](./record/pic/4-4.png)
### System V IPC
System V IPC 指的是 AT&T 在 System V.2 发行版中引入的三种进程间通信工具:
* (1)信号量,用来管理对共享资源的访问
* (2)共享内存,用来高效地实现进程间的数据共享
* (3)消息队列,用来实现进程间数据的传递。
### ipcs
* 在 Linux 中执行 ipcs 命令可以查看到当前系统中所有的 System V IPC 对象
* ipcs -a 是默认的输出全部信息、ipcs -m 显示共享内存的信息、ipcs -q 显示消息队列的信息、ipcs -s 显示信号量集的信息。另外用还有一些格式控制的参数,–t 将会输出带时间信息、-p 将输出进程 PID 信息、-c 将输出创建者/拥有者的 PID、-l 输出相关的限制条件。例如用 ipcs -ql 将显示消息队列的限制条件
```bash
ipcs
--------- 消息队列 -----------
键 msqid 拥有者 权限 已用字节数 消息
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 65536 hypo 600 524288 2 目标
0x00000000 229377 hypo 600 134217728 2 目标
.................................
--------- 信号量数组 -----------
键 semid 拥有者 权限 nsems
```
```bash
ipcs -ql
---------- 消息限制 -----------
系统最大队列数量 = 32000
最大消息尺寸 (字节) = 8192
默认的队列最大尺寸 (字节) = 16384
```
### 4-5 消息队列
屏显 4-5 msgtool 的执行结果
```bash
(base) $ ./msgtool s 1 Hello,my_msq_queue!
Sending a message
(base)$ ipcs -q
--------- 消息队列 -----------
键 msqid 拥有者 权限 已用字节数 消息
0x6d060ca4 0 hypo 660 20 1
(base) $ ./msgtool r 1
Reading a message
Type: 1 Text: Hello,my_msq_queue!
(base)$ ipcs -q
--------- 消息队列 -----------
键 msqid 拥有者 权限 已用字节数 消息
0x6d060ca4 0 hypo 660 0 0
```
### 4-6 ~ 4-10共享内存
屏显 4-6 shmget-demo 的输出
```bash
$./shmget-demo
Successfully created segment : 7634968
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 7241751 hypo 600 524288 2 目标
0x00000000 7634968 hypo 666 4096 0
Successfully created segment : 7438361
```
屏显 4-7 shmatt-write-demo 运行时的输出(1)
```bash
$./shmatt-write-demo 7634968
segment attached at 0x7f24a55f6000
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节shmatt-write-demo 映射共享内存时的进程布局
击键回车后 shmat-write-demo 将解除共享内存的映射,此时 ipcs –m 显示对应的共享内存区没有人使用(nattch 列为 0)
屏显 4-9 shmatt-demo 运行时的输出(2)
$. ipcs -m
------------ 共享内存段 --------------
键       shmid     拥有者 权限     字节     连接数 状态      
0x00000000 7667735   hypo       600        524288     2         目标      
0x00000000 7634968   hypo       666        4096       0                      
屏显 4-10 shmatt-read-demo 的部分输出
$ ./shmatt-read-demo 7634968
segment attached at 0x7f19a5aee000
------------ 共享内存段 --------------
键       shmid     拥有者 权限     字节     连接数 状态      
0x00000000 7634968   hypo       666        4096       1                      
The string in SHM is :Hello shared memory!
虽然创建该共享内存的进程已经结束了,可是 shmatt-read-demo 映射 ID 为的共享内存后,仍读出了原来写入的字符串,如所示。 连接数 状态
0x00000000 7634968 hypo 666 4096 1
0x00000000 6881306 hypo 600 2738960 2 目标
```
屏显 4-8 shmatt-write-demo 映射共享内存时的进程布局
![image](./record/pic/4-8.png)
击键回车后 shmat-write-demo 将解除共享内存的映射,此时 ipcs –m 显示对应的共享内存区没有人使用(nattch 列为 0)
屏显 4-9 shmatt-demo 运行时的输出(2)
```bash
$. ipcs -m
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 7667735 hypo 600 524288 2 目标
0x00000000 7634968 hypo 666 4096 0
```
屏显 4-10 shmatt-read-demo 的部分输出
```bash
$ ./shmatt-read-demo 7634968
segment attached at 0x7f19a5aee000
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 7634968 hypo 666 4096 1
The string in SHM is :Hello shared memory!
```
虽然创建该共享内存的进程已经结束了,可是 shmatt-read-demo 映射 ID 为的共享内存后,仍读出了原来写入的字符串,如所示。
### POSIX 有名信号量
屏显 4-11 psem-named-open-demo 的输出
```bash
$ gcc psem-named-open.c -lpthread -o psem-named-open
$ ./psem-named-open
please input a file name to act as the ID of the sem!
$ ./psem-named-open HelloWorld.c
```
屏显 4-12 ps 查看 psem-named-wait-demo 的运行状态
![image](./record/pic/4-12.png)
该信量进行 P 操作(增 1 操作),使得前面的 psem-named-wait-demo 进程从原来的阻塞状态唤醒并执行结束。
图 4-6 psem-named-post-demo 的运行输出(并唤醒阻塞的 psem-named-wait-demo 进程)
![image](./record/pic/pic4-6.png)
### POSIX 无名信号量
POSIX 无名信号量适用于线程间通信,如果无名信号量要用于进程间同步,信号量要放在共享内存中(只要该共享内存区存在,该信号灯就可用)。
### 互斥量
屏显 4-13 mutex-demo 的输出
![image](./record/pic/4-13.png)
屏显 4-14 mutex-demo 的输出
(在新版本gcc中mutex m;应改为pthread_mutex_t m;)
![image](./record/pic/4-14.png)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_SEND_SIZE 80
struct mymsgbuf {
long mtype;
char mtext[MAX_SEND_SIZE];
};
void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);
void read_message(int qid, struct mymsgbuf *qbuf, long type);
void remove_queue(int qid);
void change_queue_mode(int qid, char *mode);
void usage(void);
int main(int argc, char *argv[])
{
key_t key;
int msgqueue_id;
struct mymsgbuf qbuf;
if(argc == 1)
usage();
/* Create unique key via call to ftok() */
key = ftok(".", 'm');
/* Open the queue - create if necessary */
if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1)
{
perror("msgget");
exit(1);
}
switch(tolower(argv[1][0]))
{
case 's':send_message(msgqueue_id,(struct mymsgbuf*)&qbuf,atol(argv[2]), argv[3]);
break;
case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));
break;
case 'd': remove_queue(msgqueue_id);
break;
case 'm': change_queue_mode(msgqueue_id, argv[2]);
break;
default: usage();
}
return(0);
}
void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)
{
/* Send a message to the queue */
printf("Sending a message \n");
qbuf->mtype = type;
//填写消息的类型
strcpy(qbuf->mtext, text);
//填写消息内容
if((msgsnd(qid, (struct msgbuf *)qbuf,strlen(qbuf->mtext)+1, 0)) ==-1)
{
perror("msgsnd");
exit(1);
}
return;
}
void read_message(int qid, struct mymsgbuf *qbuf, long type)
{
/* Read a message from the queue */
printf("Reading a message \n");
qbuf->mtype = type;
msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);
printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);
return;
}
void remove_queue(int qid)
{
/* Remove the queue */
msgctl(qid, IPC_RMID, 0);
return;
}
void change_queue_mode(int qid, char *mode)
{
struct msqid_ds myqueue_ds;
/* Get current info */
msgctl(qid, IPC_STAT, &myqueue_ds);
/* Convert and load the mode */
sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);
/* Update the mode */
msgctl(qid, IPC_SET, &myqueue_ds);
return;
}
void usage(void)
{
fprintf(stderr,"msgtool - A utility for tinkering with msg queues\n");
fprintf(stderr,"nUSAGE: msgtool (s)end \n");
fprintf(stderr,"msgtool (r)ecv \n");
fprintf(stderr,"msgtool (d)elete\n");
fprintf(stderr,"msgtool (m)ode \n");
exit(1);
}
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#define thread_num 16
#define MB 1024 * 1024
int *array;
int length;//array length
int count;
int t; //number of thread
void *count3s_thread(void* id);
pthread_mutex_t m; //增加一个互斥量
int main()
{
pthread_mutex_init(&m,NULL); //初始化互斥量
int i;
int tid[thread_num];
pthread_t threads[thread_num];
length = 64 * MB;
array = malloc(length*4); //256MB
for (i = 0; i < length; i++) //initial array
array[i] = i % 2 ? 4 : 3; //偶数 i 对应数值 3
for (t = 0; t < thread_num; t++)
//循环创建 16 个线程
{
count = 0;
tid[t]=t;
int err = pthread_create(&(threads[t]), NULL, count3s_thread,&(tid[t]) );
if (err)
{
printf("create thread error!\n");
return 0;
}
}
for (t = 1; t < thread_num; t++)
pthread_join(threads[t], NULL); //等待前面创建的计数线程结束
printf("Total count= %d \n",count);
return 0;
}
void *count3s_thread(void* id)
//计数线程执行的函数
{
/*compute portion of the array that this thread should work on*/
int length_per_thread = length / thread_num;
//length of every thread
int start = *(int *)id * length_per_thread;
//every thread start position
int i;
for (i = start; i < start + length_per_thread; i++)
{
if (array[i] == 3)
{
pthread_mutex_lock(&m); //进入临界区
count++; //计数,为加入互斥保护
pthread_mutex_unlock(&m); //推出临界区
}
}
}
\ No newline at end of file
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#define thread_num 16
#define MB 1024 * 1024
int *array;
int length;//array length
int count;
int t; //number of thread
void *count3s_thread(void* id);
int main()
{
int i;
int tid[thread_num];
pthread_t threads[thread_num];
length = 64 * MB;
array = malloc(length*4); //256MB
for (i = 0; i < length; i++) //initial array
array[i] = i % 2 ? 4 : 3; //偶数 i 对应数值 3
for (t = 0; t < thread_num; t++)
//循环创建 16 个线程
{
count = 0;
tid[t]=t;
int err = pthread_create(&(threads[t]), NULL, count3s_thread,&(tid[t]) );
if (err)
{
printf("create thread error!\n");
return 0;
}
}
for (t = 1; t < thread_num; t++)
pthread_join(threads[t], NULL); //等待前面创建的计数线程结束
printf("Total count= %d \n",count);
return 0;
}
void *count3s_thread(void* id)
//计数线程执行的函数
{
/*compute portion of the array that this thread should work on*/
int length_per_thread = length / thread_num;
//length of every thread
int start = *(int *)id * length_per_thread;
//every thread start position
int i;
for (i = start; i < start + length_per_thread; i++)
{
if (array[i] == 3)
{
count++; //计数,为加入互斥保护
}
}
}
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
int main()
{
pid_t pid = 0;
int fds[2];
char buf[128];
int nwr = 0;
pipe(fds);
//在 fork()前执行
pid = fork();
if(pid < 0)
{
printf("Fork error!\n");
return -1;
}
else if(pid == 0)
{
printf("This is child process, pid = %d\n", getpid());
printf("Child:waiting for message...\n");
close(fds[1]);
//关闭写端 fds[1]
nwr = read(fds[0], buf, sizeof(buf));
//从读端 fds[0]读入数据
printf("Child:received\"%s\"\n", buf);
}
else
{
printf("This is parent process, pid = %d\n", getpid());
printf("Parent:sending message...\n");
close(fds[0]);
//关闭写端 fds[0]
strcpy(buf, "Message from parent!");
nwr = write(fds[1], buf, sizeof(buf));
//往写端 fds[1]写出数据
printf("Parent:send %d bytes to child.\n", nwr);
}
return 0;
}
\ No newline at end of file
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
sem_t *sem;
if(argc!=2)
{
printf("please input a file name to act as the ID of the sem!\n");
exit(1);
}
sem=sem_open(argv[1],O_CREAT,0644,1);
//创建一个命名的 POSIX 信号量
exit(0);
}
\ No newline at end of file
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
sem_t *sem;
int val;
if(argc!=2)
{
printf("please input a file name!\n");
exit(1);
}
sem=sem_open(argv[1],0);
sem_post(sem); //对信号量执行 P 操作(增 1)
sem_getvalue(sem,&val);
printf("value=%d\n", val);
exit(0);
}
\ No newline at end of file
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("please input a file name to act as the ID of the sem!\n");
exit(1);
}
sem_unlink(argv[1]); //撤销指定的信号量
exit(0);
}
\ No newline at end of file
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
sem_t *sem;
int val;
if(argc!=2)
{
printf("please input a file name!\n");
exit(1);
}
sem=sem_open(argv[1],0); //获取信号量对象
sem_wait(sem); //执行 P 操作(-1 操作)
sem_getvalue(sem,&val); //获得出当前信号量的值
printf("pid %ld has semaphore,value=%d\n",(long)getpid(),val);
return 0;
}
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main ( int argc, char *argv[] )
{
int shm_id ;
char * shm_buf;
if ( argc != 2 ){
printf ( "USAGE: atshm <identifier>" );
exit (1 );
}
shm_id = atoi(argv[1]);
if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ){
perror ( "shmat fail!\n" );
exit (1);
}
printf ( " segment attached at %p\n", shm_buf );
system("ipcs -m");
printf("The string in SHM is :%s\n",shm_buf); //将共享内存区的内容打印出来
getchar();
if ( (shmdt(shm_buf)) < 0 ) {
perror ( "shmdt");
exit(1);
}
printf ( "segment detached \n" );
system ( "ipcs -m " );
getchar();
exit ( 0 );
}
\ No newline at end of file
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main ( int argc, char *argv[] )
{
int shm_id ;
char * shm_buf;
if ( argc != 2 ){
printf ( "USAGE: atshm <identifier>" );
exit (1 );
}
shm_id = atoi(argv[1]);
if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ){
perror ( "shmat fail!\n" );
exit (1);
}
printf ( " segment attached at %p\n", shm_buf );
system("ipcs -m");
strcpy(shm_buf,"Hello shared memory!\n");
getchar();
if ( (shmdt(shm_buf)) < 0 ) {
perror ( "shmdt");
exit(1);
}
//映射共享内存到进程空间
//显示共享内存信息
//解除共享内存的映射
printf ( "segment detached \n" );
system ( "ipcs -m " );
getchar();
exit ( 0 );
}
\ No newline at end of file
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFSZ 4096
int main ( void )
{
int shm_id;
shm_id=shmget(IPC_PRIVATE, BUFSZ, 0666 ) ;
if (shm_id < 0 )
{
perror( "shmget fail!\n" ) ;
exit ( 1 );
}
//创建共享内存
printf ("Successfully created segment : %d \n", shm_id) ;
system( "ipcs -m");
//执行 ipcs –m 命令,显示系统的共享内存信息
return 0;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册