姓名:杨乔 学号:19020100280 学院:电子工程学院
转自:
https://blog.csdn.net/qq_41035588/article/details/92002740
【嵌牛导读】嵌入式一般指嵌入式系统。嵌入式系统由硬件和软件组成。是能够独立进行运作的器件。Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。
【嵌牛鼻子】基于ARM的嵌入式Linux开发总结
【嵌牛提问】基于ARM的嵌入式Linux开发如何使用?
【嵌牛正文】
一、Linux进程编程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配和调度的基本单位,是操作系统结构的基础。
1 进程控制
子进程创建:fork()函数
在Linux中创建一个新进程的唯一方法是使用fork()函数。fork()函数是Linux中一个非常重要的函数,和以往遇到的函数有一些区别,因为fork()函数看起来执行一次却返回两个值。
1)fork()函数说明
fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。
使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程的上下文、代码段、进程堆栈、内存信息、打开的文件描述符、符号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。
因为子进程几乎是父进程的完全复制,所以父子两进程会运行同一个程序。这就需要用一种方式来区分它们,并使它们照此运行,否则,这两个进程不可能做不同的事。
实际上是在父进程中执行fork()函数时,父进程会复制一个子进程,而且父子进程的代码从fork()函数的返回开始分别在两个地址空间中同时运行,从而使两个进程分别获得所属fork()函数的返回值,其中在父进程中的返回值是子进程的进程号,而在子进程中返回0。因此,可以通过返回值来判断该进程的父进程还是子进程。
2)fork()函数语法
进程等待函数
1)wait()函数,无条件等待,父进程阻塞直到子进程结束
2)waitpid()函数,指定等待某个子进程结束以及等待的方式(阻塞或非阻塞)
所需头文件 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t waitpid(pid_t pid, int *status, int options)
函数参数 pid pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=-1:等待任何一个子进程退出,此时和wait作用一样。
pid=0:等待其组ID等于调用进程的组ID的任一子进程。
pid<-1:等待其组ID等于pid的绝对值的任一子进程。
status 同wait
options WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0
WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。
0:同wait,阻塞父进程,等待子进程退出。
函数返回值 正常:结束的子进程的进程号
使用选项WNOHANG且没有子进程结束时:0
调用出错:-1
所需头文件 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t waitpid(pid_t pid, int *status, int options)
函数参数 pid pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=-1:等待任何一个子进程退出,此时和wait作用一样。
pid=0:等待其组ID等于调用进程的组ID的任一子进程。
pid<-1:等待其组ID等于pid的绝对值的任一子进程。
status 同wait
options WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0
WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。
0:同wait,阻塞父进程,等待子进程退出。
函数返回值 正常:结束的子进程的进程号
使用选项WNOHANG且没有子进程结束时:0
调用出错:-1
进程结束:exit()和_exit()
所需头文件 exit:#include <stdlib.h>
_exit:#include <unistd.h>
函数原型 exit:void exit(int status);
_exit:void _exit(int status);
函数传入值 status是一个整型的参数,可以利用这个参数传递进程结束时的状态。
通常0表示正常结束;其他的数值表示出现了错误,进程非正常结束。
在实际编程时,可以用wait系统调用接收子进程的返回值,进行相应的
处理。
所需头文件 exit:#include <stdlib.h>
_exit:#include <unistd.h>
函数原型 exit:void exit(int status);
_exit:void _exit(int status);
函数传入值 status是一个整型的参数,可以利用这个参数传递进程结束时的状态。
通常0表示正常结束;其他的数值表示出现了错误,进程非正常结束。
在实际编程时,可以用wait系统调用接收子进程的返回值,进行相应的
处理。
两者的区别:
(1)_exit()函数的作用最为简单:直接使进程终止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;
(2)exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。
(3)exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是"清理I/O缓冲"。
Linux下的进程间通信
进程间通信用于实现参数传递及通信功能;Linux支持的常用的进程间通信方法:管道、消息队列、共享内存、信号量、套接口等等。
实例:(1)实验三:Linux进程编程;
(2)网盘linux编程源代码目录下fork文件下相关实例(FIFO、msgque、shm)。
嵌入式知识点复习六 --arm-linux网络编程
1、程序流程
(1)网络通信程序架构-客户端/服务器架构
2、函数说明
socket()
Sockfd=socket(AF_INET,SOCK_STREAM,0);
Bind()
s_add.sin_family=AF_INET;IPV4协议
s_add.sin_addr.s_addr=inet_addr(“192.168.1.123”);IP地址192.168.1.123
s_add.sin_port=htons(0x8888);端口号是8888
if(-1 == bind(Sockfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
listen()服务器端侦听函数
listen(Sockfd,5)服务器侦听来自客户端的请求
accept()服务器端接受客户端连接请求
nfp = accept(Sockfd, (struct sockaddr *)(&c_add), sizeof(struct sockaddr);
send()数据发送函数
send(nfp,“hello,welcome to my server”,32,0)
recv()数据接收函数
recv(nfp,buffer,1024,0)
关闭连接
Close(nfp)
关闭服务器
Close(Sockfd)
实例:(1)实验四:网络聊天室设计
(2)网盘/linux编程源代码/socket下相关代码
嵌入式知识点复习七 --linux字符型设备驱动初步
一、Linux字符设备驱动初步
1、Linux设备类型
(1)字符设备:只能一个字节一个字节的读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序进行。字符设备是面向流的设备,常见的字符设备如鼠标、键盘、串口、控制台、LED等。
(2)块设备:是指可以从设备的任意位置读取一定长度的数据设备。块设备如硬盘、磁盘、U盘和SD卡等存储设备。
(3)网络设备:网络设备比较特殊,不在是对文件进行操作,而是由专门的网络接口来实现。应用程序不能直接访问网络设备驱动程序。在/dev目录下也没有文件来表示网络设备。
2、开发流程
3、关键函数讲解(以2.6以下版本内核为例)
(1)驱动模块注册register_chrdev()函数
原型:register_chrdev(unsigned int major, const char *name,const struct file_operations *fops);
major:主设备号,该值为 0 时,自动运行分配。而实际值不是 0 ;
name:设备名称;
fops:操作函数,实现驱动定义的open、read、write、close等内核函数与应用程序调用的open、read、write、close间的映射;
返回值:
major 值为 0 ,正常注册后,返回分配的主设备号。如果分配失败,返回 EBUSY 的负值 ( -EBUSY ) 。major 值若大于 linux/major.h (2.4内核)中声明的最大值 (#define MAX_CHRDEV 255) ,则返回EINVAL 的负值 (-EINVAL) 。指定 major 值后,若有注册的设备,返回 EBUSY 的负值 (-EBUSY)。若正常注册,则返回 0 值
(2)驱动注销unregister_chrdev()函数
原型:
#include <linux.fs.h>
int unregister_chrdev (unsigned int major, const char *name)
变量:
major 主设备号
name 设备文件
返回值:
major 值若大于 linux/major.h (2.4 内核)中声明的最大值 (#define MAX_CHRDEV 255),返回 EINVAL的负值 (-EINVAL)。指定了 major的值后,若将要注销的 major 值并不是注册的设备驱动程序,返回 EINVAL的负值 ( -EINVAL )。正常注销则返回 0值。
(3)File_operation结构体
file_operations结构是建立驱动程序和设备编号的连接,内部是一组函数指针,每个打开的文件,也就是file结构,和一组函数关联,这些操作主要用来实现系统调用的
struct file_operations {
struct module *owner;//拥有该结构的模块的指针,一般为THIS_MODULES
loff_t (*llseek) (struct file *, loff_t, int);//用来修改文件当前的读写位置
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//从设备中同步读取数据
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//向设备发送数据
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的读取操作
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的写入操作
int (*readdir) (struct file *, void *, filldir_t);//仅用于读取目录,对于设备文件,该字段为NULL
unsigned int (*poll) (struct file *, struct poll_table_struct *); //轮询函数,判断目前是否可以进行非阻塞的读写或写入
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //执行设备I/O控制命令
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系统,将使用此种函数指针代替ioctl
long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系统上,32位的ioctl调用将使用此函数指针代替
int (*mmap) (struct file *, struct vm_area_struct *); //用于请求将设备内存映射到进程地址空间
int (*open) (struct inode *, struct file *); //打开
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *); //关闭
int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待处理的数据
int (*aio_fsync) (struct kiocb *, int datasync); //异步刷新待处理的数据
int (*fasync) (int, struct file *, int); //通知设备FASYNC标志发生变化
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
};