学习解析嵌入式Linux开发(基于phytiumpi)(四)(进程,fork,exit,execl,进程间通信(socket,pipe))

嵌入式linux(基于飞腾派)

首先看一下phytiumpi OS 的目录结构

ren@phytiumpi:/$ ls
bin  boot  data  dev  etc  home  lib  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

这一节与前面跨度较大,学习一下关于编写嵌入式应用程序的内容

RTOS任务->linux线程

八.进程和线程

进程(process):一个内存地址空间和执行线程的组合
线程(thread):进程的执行线程

main thread: 主线程
pthread_create: 创建线程
地址空间是进程私有的,thread无法访问

8.1 进程

‘拥有’:内存映射,文件描述符,信号处理程序,当前工作目录,用户ID,组ID

8.1.1 进程的创建(POSIX)

pid_t fork(void);//pid_t为int类型,进行了重载
pid_t getpid();// 获取当前进程的 pid 值
pid_t getppid(); //获取当前进程的父进程 pid 值

创建的子进程是父进程的副本
区分方式:fork返回值:子进程为0;父进程为子进程的pid;返回值为-1表示创建失败

8.1.2 终止进程

#include <stdlib.h>
void exit(int status);

#include <unistd.h>
void _exit(int status);

exit() 函数与 _exit() 的区别就在于 exit() 函数在终止当前进程之前要检查该进程打开了哪些文件,并把文件缓冲区中的内容写回文件。
在这里插入图片描述

linux终止信号
SIGKIL(信号9): 强制终止进程

kill -9 PID          # 终止单个进程
kill -9 $(pidof 进程名)  # 终止同名所有进程 

SIGTERM(信号15):优雅终止进程

kill -15 PID          # 发送 SIGTERM 到指定进程
kill -TERM PID        # 等效写法(-TERM 是信号名称)

demo

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{
    int pid;
    int status;
    pid = fork();
    if (pid == 0) {
        printf("I am the child, PID %d\n", getpid());
        sleep(10);
        exit(42);
    } else if (pid > 0) {
        printf("I am the parent, PID %d\n", getpid());
        wait(&status);
        printf("Child terminated, status %d\n", WEXITSTATUS(status));
    } else
        perror("fork:");
    return 0;
}

运行结果

ren@phytiumpi:~/demo$ ./fork_demo
I am the parent, PID 7159
I am the child, PID 7160
Child terminated, status 42

8.1.3 进程重载execl

函数族

execl	execle	execlp
execv	execve	execvp

execl:为进程重载0-3G的用户空间,可与fork函数搭配使用

int execl(const char *path, const char *arg0, ...,NULL);

demo:简易shell

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    char command_str[128];
    int pid;
    int child_status;
    int wait_for = 1;

    while (1) {
        printf("sh> ");
        scanf("%s", command_str);
        pid = fork();
        if (pid == 0) {
            /* child */
            printf("cmd '%s'\n", command_str);
            execl(command_str, command_str, (char *)NULL);
            /* We should not return from execl, so only get 
            to this line if it failed */
            perror("exec");
            exit(1);
        }
        if (wait_for) {
            waitpid(pid, &child_status, 0);
            printf("Done, status %d\n", child_status);
        }
    }
    return 0;
}

运行结果

sh> /bin/ls
cmd '/bin/ls'
exex-demo  exex-demo.c  Makefile
Done, status 0

新建一个终端线程,查看这个进程的fd文件描述符

Linux内核对所有打开的文件有一个文件描述符表格,里面存储了每个文件描述符作为索引与这个打开文件相对应的关系
0:标准输入
1:标准输出
2:标准错误

关于文件描述符的更多内容,可以上网查询

ren@phytiumpi:~/demo/exex-demo$ pidof exex-demo
16223
ren@phytiumpi:~/demo/exex-demo$ ls -l /proc/16223/fd
total 0
lrwx------ 1 ren ren 64 Cax  8 12:19 0 -> /dev/pts/0
lrwx------ 1 ren ren 64 Cax  8 12:19 1 -> /dev/pts/0
lrwx------ 1 ren ren 64 Cax  8 12:19 2 -> /dev/pts/0

8.2 进程间通信

两种通信方式:
1.将信息从一个地址空间复制到另一个地址空间
2.创建一个既可以访问又可以复制数据的内存区域

进程间通信(Inter-Process Communication IPC)是多进程协作的基础,在进程间传递数据

同步IPC和异步IPC:同步IPC指它的IPC操作(如Send)会阻塞进程直到该操作完成;而异步IPC则通常是非阻塞的,进程只要发起一次操作即可返回,而不需要等待其完成

超时机制:扩展了通信双方的接口,允许发送者/接收者指定它们发送/接收请求的等待时间

进程间通信机制:管道(Pipe)、信号(Signal)、套接字(Socket)、共享内存(Shared Memory)、消息队列(Message Queue)、信号量(Semaphore)

8.2.1 套接字(简略介绍)

套接字类型:
1.SOCK_STREAM:流式套接字,用于TCP协议
2.SOCK_DGRAM:数据报套接字,用于UDP协议

既可用于本地,又可跨网络使用。如 ROS 使用套接字作为进程间通信方案
进程间通信可以使用不同的协议,如 TCP 和 UDP

8.2.2 管道(pipe)

(1)父进程创建管道,得到两个⽂件描述符指向管道的两端

(2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。

(3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信

原文链接:https://blog.csdn.net/skyroben/article/details/71513385



共享内存(Shared Memory)、消息队列(Message Queue)、信号量(Semaphore)会在下一期详细介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值