我是靠谱客的博主 单纯火龙果,最近开发中收集的这篇文章主要介绍linux虚拟机虚拟串口通信,虚拟机串口与主机串口通信·小程序(下),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

上次说到的,不能做到实时通信。那么开两个进程就可以了,一个用来监听是否有消息传来,一个用来等待用户输入。那么,先来复习一下进程的相关概念。

进程结构

linux中进程包含PCB(进程控制块)、程序以及程序所操纵的数据结构集,可分为“代码段”、“数据段”和“堆栈段”。

进程状态

运行状态R(TASK_RUNNING)

可中断睡眠状态S(TASK_INTERRUPTIBLE)

不可中断睡眠状态D(TASK_UNINTERRUPTIBLE)

暂停状态T(TASK_STOPPED或TASK_TRACED)

僵死状态Z(TASK_ZOMBIE)

退出状态X(TASK_DEAD)

ps -aux 查看进程信息,可以看到各进程的状态:

089c436026a03593c5c4a0353cca3e6d.png

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系统调用

#include < sys/types.h>

#include < unistd.h>

pid_t fork(void);

返回:子进程中为0,父进程中为子进程I D,出错为-1

注意:
1、使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:

进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。

2、子进程与父进程的区别在于:

1)父进程设置的锁,子进程不继承

2)各自的进程ID和父进程ID不同

3)子进程的未决告警被清除;

4)子进程的未决信号集设置为空集。

3、fork系统调用之后,父子进程将交替执行。

4、如果父进程先退出,子进程还没退出。那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)

5、如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。(这是不好的,这样子进程会一直占用内存资源)

解决办法:

1)wait函数:使父进程阻塞,直到一个子进程结束或者该进程收到一个指定信号为止。(但是,这样不好)

2)signal(SIGCHLD,SIG_IGN)。表示父进程忽略SIGCHLD,该信号是子进程退出的时候向父进程发出的,由init进程收。

测试

接下来,可以继续我们上次的小程序了。

#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;

}

*/

运行结果:

75ea1af67a42768bb0fbf263d1f2ca20.png


发现问题了没?对的。父进程会先死。

程序运行时:

b7a3c021a7df327dfee9af7503bbbbf4.png

程序结束时:

38291d40f6ef4714be7239c4261d92e0.png

如何解决呢?下次说~

最后

以上就是单纯火龙果为你收集整理的linux虚拟机虚拟串口通信,虚拟机串口与主机串口通信·小程序(下)的全部内容,希望文章能够帮你解决linux虚拟机虚拟串口通信,虚拟机串口与主机串口通信·小程序(下)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部