提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
系统调用
系统调用(system call)其实是Linux内核提供给应用层的应用编程接口(API),是Linux应用层进入内核的入口。不止Linux系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。
系统调用(system call)其实是Linux内核提供给应用层的应用编程接口(API),是Linux应用层进入内核的入口。不止Linux系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。
通过系统调用API,应用层可以实现与内核的交互。应用程序通过调用API函数来使用内核提供的服务,资源,以及各种各样的功能。
一、应用编程与裸机编程、驱动编程有什么区别?
1、裸机编程:
一般来说,51、STM32这类单片机的软件通常是裸机程序开发。没有操作系统的编程环境,编写直接在硬件上运行的程序,没有操作系统的支持。
2、Linux驱动编程:
Linux驱动编程指的是基于内核驱动框架开发驱动程序,驱动开发工程师通过调用Linux内核提供的接口完成设备驱动的注册,驱动程序负责底层硬件操作相关逻辑。
3、Linux应用编程:
指的是基于Linux操作系统的应用编程,在应用程序中通过调用系统调用API完成应用程序的功能和逻辑,应用程序运行于操作系统之上。通常在操作系统下有两种不同的状态:内核态和用户态,应用程序运行在用户态、而内核则运行在内核态。
二、举例说明三者区别
1、裸机程序:可以看到在裸机程序当中,LED硬件操作代码与用户逻辑代码全部都是在同一个源文件(同一个工程)中实现的,硬件操作代码与用户逻辑代码没有隔离,没有操作系统支持,代码编译之后直接在硬件平台运行,俗称“裸跑”。
static void led_on(void)
{
/* 点亮LED硬件操作代码 */
}
static void led_off(void)
{ /* 熄灭LED硬件操作代码 */
}
int main(void)
{ /* 用户逻辑 */
for ( ; ; )
{
led_on(); //点亮LED
delay(); //延时
led_off(); //熄灭LED
delay(); //延时
}
}
2、Linux下LED驱动程序示例:
此驱动程序使用了最基本的字符设备驱动框架编写。led_fops对象中提供了open、write、release方法。当应用程序调用open系统调用打开此LED设备时会执行到led_open函数,调用close系统调用
//此示例代码来自于正点原子《MX6U 嵌入式 Linux C 应用编程指南》
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
static void led_on(void)
{
/* 点亮LED硬件操作代码 */
}
static void led_off(void)
{
/* 熄灭LED硬件操作代码 */
}
static int led_open(struct inode *inode, struct file *filp)
{
/* 打开设备时需要做的事情 */
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *offt)
{
int flag;
/* 获取应用层write的数据,存放在flag变量 */
if (copy_from_user(&flag, buf, size))
return -EFAULT; /* 判断用户写入的数据,如果是0则熄灭LED,如果是非0则点亮LED */
if (flag)
led_on();
else
led_off();
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
/* 关闭设备时需要做的事情 */
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int led_probe(struct platform_device *pdev)
{
/* 驱动加载时需要做的事情 */
}
static int led_remove(struct platform_device *pdev)
{
/* 驱动卸载时需要做的事情 */
}
static const struct of_device_id led_of_match[] = {
{ .compatible = "alientek,led", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, led_of_match);
static struct platform_driver led_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "led",
.of_match_table = led_of_match,
},
.probe = led_probe,
.remove = led_remove,
};
module_platform_driver(led_driver);
MODULE_DESCRIPTION("LED Driver");
MODULE_LICENSE("GPL");
3、Linux下LED应用程序
此应用程序也非常简单,仅只需实现用户逻辑代码即可,循环点亮、熄灭LED,并不需要实现硬件操作相关,示例代码中调用了open、write、close这三个系统调用API接口,open和close分别用于打开/关闭LED设备,write写入数据传给LED驱动,传入0熄灭LED,传入非0点亮LED。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd;
int data;
fd = open("/dev/led", O_WRONLY);//打开LED设备(假定LED的设备文件为/dev/led)
if (0 > fd)
return -1;
for ( ; ; )
{
data = 1;
write(fd, &data, sizeof(data)); //写1点亮LED sleep(1); //延时1秒
data = 0;
write(fd, &data, sizeof(data)); //写0熄灭LED sleep(1); //延时1秒
}
close(fd);
return 0;
}
总结
LED应用程序与LED驱动程序是分隔、分离的,它们单独编译,它们并不是整合在一起的,应用程序运行在操作系统之上,有操作系统支持,应用程序处于用户态,而驱动程序处于内核态,与纯粹的裸机程序存在着质的区别。
本文详细介绍了裸机编程、Linux驱动编程和Linux应用编程的区别。裸机编程是在没有操作系统环境下直接针对硬件进行编程;Linux驱动编程涉及与内核交互,实现设备控制;而Linux应用编程则是在操作系统支持下,通过系统调用API实现功能。通过LED控制的实例,展示了三种编程方式在实现相同功能时的不同实现方式和层次划分。
&spm=1001.2101.3001.5002&articleId=125303253&d=1&t=3&u=9944736e5453408cb58f8eb2955fca99)
2356

被折叠的 条评论
为什么被折叠?



