Linux应用编程记录(一)

本文详细介绍了裸机编程、Linux驱动编程和Linux应用编程的区别。裸机编程是在没有操作系统环境下直接针对硬件进行编程;Linux驱动编程涉及与内核交互,实现设备控制;而Linux应用编程则是在操作系统支持下,通过系统调用API实现功能。通过LED控制的实例,展示了三种编程方式在实现相同功能时的不同实现方式和层次划分。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


系统调用

系统调用(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驱动程序是分隔、分离的,它们单独编译,它们并不是整合在一起的,应用程序运行在操作系统之上,有操作系统支持,应用程序处于用户态,而驱动程序处于内核态,与纯粹的裸机程序存在着质的区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值