上次说到的,不能做到实时通信。那么开两个进程就可以了,一个用来监听是否有消息传来,一个用来等待用户输入。那么,先来复习一下进程的相关概念。
<br>
进程结构
linux中进程包含PCB(进程控制块)、程序以及程序所操纵的数据结构集,可分为“代码段”、“数据段”和“堆栈段”。
进程状态
运行状态R(TASK_RUNNING)
可中断睡眠状态S(TASK_INTERRUPTIBLE)
不可中断睡眠状态D(TASK_UNINTERRUPTIBLE)
暂停状态T(TASK_STOPPED或TASK_TRACED)
僵死状态Z(TASK_ZOMBIE)
退出状态X(TASK_DEAD)
ps -aux 查看进程信息,可以看到各进程的状态:
init进程
所有进程的父进程
init进程绝不会终止。
它是一个普通的用户进程(与交换进程不同,它不是内核中的系统进程),但是它以超级用户特权运行。
获取进程标识
#include < sys/types.h>
#include < unistd.h>
pid_t getpid(void); 返回:调用进程的进程I D
pid_t getppid(void); 返回:调用进程的父进程I D
uid_t getuid(void); 返回:调用进程的实际用户I D
uid_t geteuid(void); 返回:调用进程的有效用户I D
gid_t getgid(void); 返回:调用进程的实际组I D
gid_t getegid(void); 返回:调用进程的有效组I D
fork系统调用
1
2
3
4#include < sys/types.h> #include < unistd.h> pid_t fork(void); 返回:子进程中为0,父进程中为子进程I D,出错为-1
注意:
<br>1、使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:
进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
2、子进程与父进程的区别在于:
1)父进程设置的锁,子进程不继承
2)各自的进程ID和父进程ID不同
3)子进程的未决告警被清除;
4)子进程的未决信号集设置为空集。
3、fork系统调用之后,父子进程将交替执行。
4、如果父进程先退出,子进程还没退出。那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)
5、如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。(这是不好的,这样子进程会一直占用内存资源)
解决办法:
1)wait函数:使父进程阻塞,直到一个子进程结束或者该进程收到一个指定信号为止。(但是,这样不好)
2)signal(SIGCHLD,SIG_IGN)。表示父进程忽略SIGCHLD,该信号是子进程退出的时候向父进程发出的,由init进程收。
测试
接下来,可以继续我们上次的小程序了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136#include < stdio.h> #include < sys/types.h> #include < signal.h> #include " port.h" #include " readConfig.h" // 1、主机与虚拟机 int main() { int fd,pid,child_id; char filename[20] = "serial.cfg"; char recbuf[100] = ""; char sendbuf[100] = ""; struct t_port port = {0}; //从文件获取配置信息 getMsg(filename,&port); //串口初始化 fd = portInit(port.devname,port.speed,port.data,port.parity,port.stop); //主机与虚拟机串口通信 pid = fork(); if(pid == -1) { perror("create process"); return 1; } else if(pid == 0) //子进程 接收消息 { child_id = getpid(); while(read(fd,recbuf,100)>0) //这里不能用strlen。因为开始strlen(recbuf)=0 { if(strcmp(recbuf,"") != 0) { printf("receive msg: %sn",recbuf); putchar('$'); fflush(stdout); } memset(recbuf,0,100); } } else //(主)父进程 发送消息 { printf("$"); while(1) { memset(sendbuf,0,100); scanf("%s",sendbuf); if(strcmp(sendbuf,"over") == 0) //但是,此时,子进程未结束,还在后台运行 { break; } if(write(fd,sendbuf,strlen(sendbuf)) > 0) { printf("$"); } } } close(fd); return 0; } //2、虚拟机两串口 /* int main(int argc,char *argv[]) { int fd,pid; char receivebuf[100] = ""; char sendbuf[100] = ""; if(argc != 2) { printf("format error!n"); return 1; } if( strcmp(argv[1],"ttyS0")==0) { fd = portInit("/dev/ttyS0",115200,8,0,1); } else if(strcmp(argv[1],"ttyS1")==0) { fd = portInit("/dev/ttyS1",115200,8,0,1); } else { printf("format error!n"); return 1; } pid = fork(); if(pid == -1) { perror("create process"); return 1; } else if(pid == 0) //子进程 { //接收消息 while(read(fd,receivebuf,sizeof(receivebuf)) > 0) { if(strcmp(receivebuf,"") != 0) { printf("receive msg : %sn",receivebuf); } memset(receivebuf,0,100); } } else //父进程 { //发送消息 while(1) { memset(sendbuf,0,100); scanf("%s",sendbuf); if(strcmp(sendbuf,"-over") == 0) { break; } write(fd,sendbuf,strlen(sendbuf)); printf("send OKn"); } } close(fd); return 0; } */
运行结果:
<br>发现问题了没?对的。父进程会先死。
程序运行时:
程序结束时:
如何解决呢?下次说~
转载于:https://blog.51cto.com/13097817/2049588
最后
以上就是满意八宝粥最近收集整理的关于虚拟机串口与主机串口通信·小程序(下)的全部内容,更多相关虚拟机串口与主机串口通信·小程序(下)内容请搜索靠谱客的其他文章。
发表评论 取消回复