-
系统编程第五天
今天是系统编程最后一天,讲的主要是管道和共享内存以及信号量,看着老师的代码也不是很难,就是自己写有难度。老师留的作业在逻辑上也很简单,就是敲代码不容乐观,接下来两天就要积累代码量了。
进程间通信
一、信号(必须掌握,但不常用)
int kill(pid_t pid, int signo);//给进程号为pid的进程发送signo号信号
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
sigaction/sigemptyset函数示例:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void MyHandle(int sig);
int main(int argc,char *argv[])
{
struct sigaction act;
act.sa_handler = SIG_DFL;//MyHandle;//SIG_IGN
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT,&act,NULL);
while(1)
{
sleep(1);
}
return 0;
}
void MyHandle(int sig)
{
printf("In SIGINT Handler:%d\n",sig);
}
二、匿名管道(父子进程间,必须掌握,但不常用)
int pipe(int fd[2]);
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
char name[20];
int id;
};
int main(int argc,char *argv[])
{
int arrfd[2];
int ret = 0;
pid_t pid;
char buf[6];
struct Stu st = {"Zhangsan",16};
struct Stu sts = {""};
ret = pipe(arrfd);
if(ret < 0)
{
printf("Pipe Error\n");
return 1;
}
pid = fork();
switch(pid)
{
case 0://child process
close(arrfd[1]);
read(arrfd[0],buf,6);
read(arrfd[0],&sts,sizeof(sts));
printf("%s\n",buf);
printf("name:%s id:%d\n",sts.name,sts.id);
close(arrfd[0]);
break;
case -1:
printf("Fork Error");
break;
default://parent process
close(arrfd[0]);
sleep(2);
write(arrfd[1],"hello",sizeof("hello"));
write(arrfd[1],&st,sizeof(st));
close(arrfd[1]);
break;
}
return 0;
}
数组类型作为形参类型时完全等价于一个指针类型
T arr[]=====>T *p
T arr[][3]=======>T (*p)[3]
T arr[][4][5]=======>T (*p)[4][5]
1. N维数组都可以看成一维数组,这个一维数组里元素是(N-1维的数组)
2. 数组作为函数形参时,它完全等价于指向数组元素的指针
3. 数组名在表达式中单独出现时,它相对于指向下标为0的元素的只读指针
三、有名管道(重点)
int mkfifo(const char *pathname, mode_t mode);
配套函数:open close read write
范例见testfifo目录(涉及多个'.c'文件就不展示了)
四、消息队列(简单了解)
使用队列管理消息,一个进程向队尾中放消息(即在队尾插入链表节点),另一个进程则从队头取消息(即移除队头链表节点)
五、共享内存(重点)
id = shmget(...)
void *p = shmat(id);
......
shmdt(id);
shmctl(id,IPC_RMID,NULL);
范例见testshm目录(涉及多个'.c'文件就不展示了)
六、信号量集合(重点):semphore set一个信号量集可以管理多个信号量
int semget(9876, int nsems, int semflg);
int semop(int semid, struct sembuf *opsptr, size_t nops);
struct sembuf
{
short sem_num;//表示该操作的信号量在信号量集中的下标
short sem_op;//> 0:V操作 ; <0: 等待资源的P操作 ;=0:等待记分牌为0的P操作
short sem_flg; //填0
}
调用示例:
struct sembuf arr[3] = {{0,1,0},{2,-3,0},{5,0,0}};
semop(id,arr,3);
int semctl(int semid, int semnum, int cmd, ...);
cmd: IPC_RMID 删除信号量集合,第四个填NULL
SETVAL:
union semun x;//需要自己定义,在(man semctl中有现成的)
x.val = 6;
semctl(id,0,SETVAL,x);
SETALL:
union semun x;
unsigned short arr[3] = {5,9,2};
x.array = arr;
semctl(id,0,SETALL,x);
创建一个仅包含一个信号量的信号量集合以及相关操作的封装示例代码见:testsemset目录(涉及多个'.c'文件就不展示了)
与共享内存联用的示例代码见:testshmsem目录(涉及多个'.c'文件就不展示了)
七、共享文件(简单了解)
八、Socket通信(可以跨电脑进行通信,重点,难点)
C语言的核心:函数
灵魂:数据类型
1. sizeof
2. 变量定义语句的含义
三步四属性:
三步:a. 给变量分配空间 b.给空间命名 c. 决定空间二进制位的含义
四属性:显式属性:名字 类型
隐式属性:空间首地址(左值) 内容(右值)
3. 相关运算
4. 函数形参类型
5. 函数返回值类型
```
>作业:
1.使用共享内存和信号量集完成如下程序:两个进程同时向共享内存写入字符串,一个写全大写的A字符20个,另一个写全小写的a字符20个,要求共享内存中不可同时有A和a。第三个进程负责从共享内存中读出内容并打印出来
2.通过有名管道实现:A进程向B进程发送10个整型数,B进程则向A进程发送这10个数中的最大数,A收到后打印该最大数。
网友评论