当前位置: 首页 > news >正文

做深圳门户网站起什么名字好推广营销策划方案

做深圳门户网站起什么名字好,推广营销策划方案,免费制作微信网页网站,行业应用服务类appfile_operations结构体中的函数就是我们要实现的具体操作函数。 注意: register_chrdev()和 unregister_chrdev()这两个函数是老版本驱动使用的。现在新字符设备驱动已经不再使用这两个函数,而是使用Linux内核推荐的新字符设备驱动API函数。 1、创建C…

file_operations结构体中的函数就是我们要实现的具体操作函数。

注意:

register_chrdev()和 unregister_chrdev()这两个函数是老版本驱动使用的。现在新字符设备驱动已经不再使用这两个函数,而是使用Linux内核推荐的新字符设备驱动API函数

1、创建CharDeviceXXX.c

输入“cd /home/zgq/linux/Linux_Drivers/回车”,切换到“/home/zgq/linux/Linux_Drivers/”目录

输入“ls回车”,查看“/home/zgq/linux/Linux_Drivers/”目录

输入“mkdir CharDeviceXXX回车”,创建“CharDeviceXXX”目录

输入“ls回车”,查看“/home/zgq/linux/Linux_Drivers/”目录

输入“cd CharDeviceXXX回车”,切换到“/home/zgq/linux/Linux_Drivers/ CharDeviceXXX/”目录

输入“vi CharDeviceXXX.c回车”,打开“CharDeviceXXX.c

CharDeviceXXX.c文件如下:

#include <linux/types.h>

//数据类型重命名

//使能bool,u8,u16,u32,u64, uint8_t, uint16_t, uint32_t, uint64_t

//使能s8,s16,s32,s64,int8_t,int16_t,int32_t,int64_t

#include <linux/kernel.h>     //必须要包含的头文件

#include <linux/delay.h>

#include <linux/ide.h>

#include <linux/init.h>

#include <linux/module.h>     //必须要包含的头文件

#include <linux/string.h>     //下面要用到字符串,显然也要包含

//#include <linux/device.h>     //必须要包含的头文件

//#include <linux/fs.h>         //使能结构体"file_operations"

#define CharDeviceXXX_MAJOR   200

//定义主设备号

//静态分配设备号:在串口输入“cat/proc/devices”查询当前已用的主设备号

//然后使用一个“没有被使用的设备号”作为该设备的的主设备号

#define CharDeviceXXX_NAME   "CharDeviceXXXName"  //定义设备的名字

static char CharDeviceXXX_readbuf[100]; //读缓冲区

static char CharDeviceXXX_writebuf[100]; //写缓冲区

static char My_DataBuffer[] = {"My Data!"};

/* 打开设备 */

static int CharDeviceXXX_open(struct inode *inode, struct file *filp)

{

  /* 用户实现具体功能 */

  printk("CharDeviceXXX_open!\r\n");

  return 0;

}

/* 从设备读取数据,保存到首地址为buf的数据块中,长度为cnt个字节 */

//file结构指针变量flip表示要打开的设备文件

//buf表示用户数据块的首地址

//cnt表示用户数据的长度,单位为字节

//loff_t结构指针变量offt表示“相对于文件首地址的偏移”

static ssize_t CharDeviceXXX_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)

{

  int ret = 0;

  memcpy(CharDeviceXXX_readbuf, My_DataBuffer,sizeof(My_DataBuffer));

  //将My_DataBuffer[]中的所有数据拷贝到CharDeviceXXX_readbuf[]

  ret = copy_to_user( buf, CharDeviceXXX_readbuf, cnt );

  //将CharDeviceXXX_readbuf[]中的前cnt个字节拷贝到buf[]中

  if(ret==0) printk("Send the data to the user, and the result is ok!\r\n");

  else printk("Send the data to the user, and the result is failed!\r\n");

  return 0;

}

/* 向设备写数据,将数据块首地址为buf的数据,长度为cnt个字节,发送给用户 */

//file结构指针变量flip表示要打开的设备文件

//buf表示用户数据块的首地址

//cnt表示用户数据的长度,单位为字节

//loff_t结构指针变量offt表示“相对于文件首地址的偏移”

static ssize_t CharDeviceXXX_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)

{

  int ret = 0;

  ret = copy_from_user(CharDeviceXXX_writebuf, buf, cnt);

  //将buf[]中的前cnt个字节拷贝到CharDeviceXXX_writebuf[]中

  if(ret==0) printk("Receive the data form user , and the result is ok!\r\n");

  else printk("Receive the data form user , and the result is failed!\r\n");

  return 0;

}

/* 关闭/释放设备 */

static int CharDeviceXXX_release(struct inode *inode, struct file *filp)

{

  /* 用户实现具体功能 */

  printk("CharDeviceXXX_release!\r\n");

  return 0;

}

/*声明file_operations结构变量MyCharDevice_fops*/

/*它是指向设备的操作函数集合变量*/

const struct file_operations CharDeviceXXX_fops = {

  .owner = THIS_MODULE,

  .open = CharDeviceXXX_open,

  .read = CharDeviceXXX_read,

  .write = CharDeviceXXX_write,

  .release = CharDeviceXXX_release,

};

/*驱动入口函数 */

static int  __init CharDeviceXXX_init(void)

{

  int ret;

  ret = register_chrdev(CharDeviceXXX_MAJOR, CharDeviceXXX_NAME, &CharDeviceXXX_fops);

  //注册字符设备驱动

  //CharDeviceXXX_MAJOR为主设备号,采用宏CharDeviceXXX_NAME定义设备名字

  //CharDeviceXXX_fops是设备的操作函数集合,它是file_operations结构变量

  if (ret < 0)

  {

    pr_err("CharDeviceXXX_init is failed!!!\r\n");

    return ret;

  }

  else pr_err("CharDeviceXXX_init is ok!!!\r\n");

  return 0;

}

/*驱动出口函数 */

static void __exit CharDeviceXXX_exit(void)

{/*出口函数具体内容 */

  unregister_chrdev(CharDeviceXXX_MAJOR, CharDeviceXXX_NAME);

  //注销字符设备驱动

  //CharDeviceXXX_MAJOR为主设备号,采用宏CharDeviceXXX_NAME定义设备名字

}

module_init(CharDeviceXXX_init);

//指定CharDeviceXXX_init()为驱动入口函数

module_exit(CharDeviceXXX_exit);

//指定CharDeviceXXX_exit()为驱动出口函数

MODULE_AUTHOR("Zhanggong");//添加作者名字

MODULE_LICENSE("GPL");//LICENSE采用“GPL协议”

MODULE_INFO(intree,"Y");

//去除显示“loading out-of-tree module taints kernel.”

2、Makefile文件的一般模板

输入“vi Makefile回车

KERNELDIR := /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31

#使用“:=”将其后面的字符串赋值给KERNELDIR

CURRENT_PATH := $(shell pwd)

#采用“shell pwd”获取当前打开的路径

#使用“$(变量名)”引用“变量的值”

obj-m := CharDeviceXXX.o

#生成“obj-m”需要依赖“CharDeviceXXX.o

build: kernel_modules

#生成“build”需要依赖“kernel_modules”

@echo $(KERNELDIR)

#输出KERNELDIR的值为“/home/zgq/linux/atk-mp1/linux/linux-5.4.31”

@echo $(CURRENT_PATH)

#输出CURRENT_PATH的值为/home/zgq/linux/Linux_Drivers/CharDeviceXXX

@echo $(MAKE)

#输出MAKE的值为make

kernel_modules:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

#后面的"modules"表示编译成模块

#“KERNELDIR”上面定义为“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目录”

#“CURRENT_PATH”上面定义为“当前的工作目录”

#“-C $(KERNELDIR) M=$(CURRENT_PATH) ”表示将“当前的工作目录”切换到“指定的目录”中

#即切换到“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”。

#M表示模块源码目录

#在“make和modules”之间加入“M=$(CURRENT_PATH)”,表示切换到由“CURRENT_PATH”指定的目录中读取源码,同时将其编>译为.ko 文件

clean:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

#“KERNELDIR”上面定义为“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目录”

#“CURRENT_PATH”上面定义为“当前的工作目录

3、创建“c_cpp_properties.json

打开VSCode,按下“Ctrl+Shift+P”,打开VSCode控制台,然后输入“C/C++:Edit Configurations(JSON)”,见下图:

打开以后会自动在“.vscode ”目录下生成一个名为“c_cpp_properties.json” 的文件,此文件默认内容如下所示:

{

    "configurations": [

        {

            "name": "Linux",

            "includePath": [

                "${workspaceFolder}/**"

            ],

            "defines": [],

            "compilerPath": "/usr/bin/gcc",

            "cStandard": "gnu11",

            "cppStandard": "gnu++14",

            "intelliSenseMode": "gcc-x64"

        }

    ],

    "version": 4

}

修改“includePath”后,“c_cpp_properties.json”文件如下:

{

    "configurations": [

        {

            "name": "Linux",

            "includePath": [

                "${workspaceFolder}/**",

"/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31",

"/home/zgq/linux/Linux_Drivers/CharDeviceXXX_1",

"/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include",

"/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/include",

"/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include/generated"

],

            "defines": [],

            "compilerPath": "/usr/bin/gcc",

            "cStandard": "gnu11",

            "cppStandard": "gnu++14",

            "intelliSenseMode": "gcc-x64"

        }

    ],

    "version": 4

}

4、了解APP程序需要用到的相关函数

编写Linux应用程序,需要用到C库里面“和文件操作有关”的函数。

1)、open()函数

int open(const char *pathname, int flags)

指针变量pathname表示要打开的设备文件名;

flags表示“文件打开模式”:O_RDONLY表示只读模式;

O_WRONLY表示只写模式;

O_RDWR表示读写模式;

其他可选模式:O_APPEND表示每次写操作都写入文件的尾部;O_CREAT表示如果指定文件不存在,则创建这个文件;

O_EXCEL表示如果要创建的文件已经存在,则返回-1,并修改errno的值;O_TRUNC表示如果文件存在,并且以“只写或读写”方式打开,则清空文件全部内容;O_NOCTTY表示如果路径名指向终端设备,不要把这个设备用作控制终端;O_NONBLOCK表示如果路径名指向FIFO/块文字/字符文件,则把文件的打开和后继I/O设置为非阻塞;O_DSYNC表示等待物理I/O结束后再write。在不影响读取新写入的数据的前提下,不等待文件属性更新;O_RSYNC表示read等待所有写入同一区域的写操作完成后再进行;O_SYNC表示等待物理I/O结束后再write,包括更新文件属性的IO;

返回值:如果文件打开成功,则返回“文件描述符”。

在终端输入“man 2 open”可以查询open()这个函数

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

需要包含上面的头文件,才可以使用open()函数

2)、read()函数

ssize_t read(int fd, void *buf, size_t count)

fd表示要进行读操作的“文件描述符”

buf表示将读到的数据保存到“以buf为首地址的数据块”

count表示读取到的“数据长度”,单位为字节

返回值:

大于0表示读取到的字节数

0表示读到了文件的尾部

小于0表示读取失败

在终端输入“man 2 read”可以查询read()这个函数

#include <unistd.h>

需要包含上面这个头文件,才可以使用read()函数

3)、write()函数

ssize_t write(int fd, const void *buf, size_t count)

fd表示要进行写操作的“文件描述符”

buf和count表示将“以buf为首地址的数据块”,长度为count个字节,发送给用户

返回值:

大于0表示写入的字节数

0表示没有写入任何数据

小于0表示写入失败

在终端输入“man 2 write”可以查询write()这个函数

#include <unistd.h>

需要包含上面这个头文件,才可以使用write()函数

4)、close()函数

int close(int fd)

fd表示要关闭的“文件描述符”

返回值:

0表示关闭成功

小于0表示关闭失败

在终端输入“man 2 close”可以查询close()这个函数

#include <unistd.h>

需要包含上面这个头文件,才可以使用close()函数

在终端输入“man 3 memcpy”在第3节中可以查询memcpy()这个函数

#include <string.h>

需要包含上面这个头文件,才可以使用memcpy()函数

linux之man命令 (baidu.com)

man后面的数字代表的内容

1:用户在shell环境可操作的命令或执行文件;如输入“man 1 ls”就可以查询ls命令

2:系统内核可调用的函数与工具等;如输入“man 2 read”就可以查询read()函数

3:一些常用的函数(function)与函数库(library),大部分为C的函数库(libc);

;如输入“man 3 strstr”就可以查询strstr()函数

4:设备文件说明,通常在/dev下的文件

5:配置文件或某些文件格式

6:游戏(games)

7:惯例与协议等,如Linux文件系统,网络协议,ASCII code等说明

8:系统管理员可用的管理命令

9:跟kernel有关的文件。

5、编写CharDeviceXXX_APP.c

#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/stat.h"

#include "fcntl.h"

#include "stdlib.h"

#include "string.h"

static char usrdataBuffer[] = {"usr data!"};

//例如当argv[]是指向输入参数“./CharDeviceXXX /dev/chrdevbase 1”

/*

参数argc: argv[]数组元素个数

参数argv[]:是一个指针数组

返回值: 0 成功;其他 失败

*/

int main(int argc, char *argv[])

{

  int fd, retvalue;

  char *filename;

  char readbuf[100], writebuf[100];

  if(argc != 3)

  {

    printf("Error Usage!\r\n");

    return -1;

  }

  //argv[]是指向输入参数“./CharDeviceXXXApp” “/dev/CharDeviceXXX” “1”

  filename = argv[1];

  //argv[1]指向字符串“/dev/CharDeviceXXX”

  fd = open(filename, O_RDWR);

  //以“读写方式”打开“/dev/CharDeviceXXX”文件,若成功则fd为“文件描述符”

  //fd=0表示标准输入流; fd=1表示标准输出流;fd=2表示错误输出流;

  if(fd < 0)

  {

    printf("Can't open file %s\r\n", filename);

    return -1;

  }

  else printf("open file: %s\r\n", filename);

  if(atoi(argv[2]) == 1)

  {

    retvalue = read(fd, readbuf, 50);

    //fd表示要进行读操作的“文件描述符”

    //readbuf表示将读到的数据保存到“以readbuf为首地址的数据块”

    //50表示读取到的“数据长度”,单位为字节

    //返回值大于0表示读取到的字节数

    //返回值为0表示读到了文件的尾部

    //返回值小于0表示读取文件失败

    if(retvalue < 0)//读取文件失败

    {

      printf("read file %s failed!\r\n", filename);

    }

    else//读取文件成功

    {

      printf("read data:%s\r\n",readbuf);

    }

  }

  if(atoi(argv[2]) == 2)

  {

memcpy(writebuf, usrdataBuffer, sizeof(usrdataBuffer));

//将usrdataBuffer[]中所有数据拷贝到writebuf[]

    retvalue = write(fd, writebuf, 50);

    //fd=2表示要进行写操作的“文件描述符”

    //将writebuf[]中前50个字节发送给用户

    //返回值大于0表示写入的字节数;

    //返回值等于0表示没有写入任何数据;

    //返回值小于0表示写入失败

    if(retvalue < 0)

    {

      printf("write file %s failed!\r\n", filename);

    }

  }

  /* 关闭设备 */

  retvalue = close(fd);

  //fd表示要关闭的“文件描述符”

  //返回值等于0表示关闭成功

  //返回值小于0表示关闭失败

  if(retvalue < 0)

  {

    printf("Can't close file %s\r\n", filename);

    return -1;

  }

  return 0;

}

6、编写脚本文件

CharDeviceXXX_APP.sh文件内容如下:

#!/bin/sh

file="CharDeviceXXX_APP"

if [ -s $file ]

#"-s $file"检测文件是否为空(文件大小是否大于0),不为空返回 true

then

rm CharDeviceXXX_APP

echo clear CharDeviceXXX_APP

else

arm-none-linux-gnueabihf-gcc CharDeviceXXX_APP.c -o CharDeviceXXX_APP

echo CharDeviceXXX_APP

fi

7、测试

输入“make回车”编译生成“CharDeviceXXX.ko

输入“chmod 777 CharDeviceXXX_APP.sh回车

将“CharDeviceXXX_APP.sh”赋可执行权限

输入“./CharDeviceXXX_APP.sh回车”,编译生成“CharDeviceXXX_APP”文件

输入“sudo cp CharDeviceXXX.ko CharDeviceXXX_APP /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -f回车

启动开发板,从网络下载程序

输入“root

输入“cd /lib/modules/5.4.31/回车

切换到“/lib/modules/5.4.31/”目录

注意:“lib/modules/5.4.31/在虚拟机中是位于“/home/zgq/linux/nfs/rootfs/”目录下,但在开发板中,却是位于根目录中

输入“ls”查看“CharDeviceXXX.ko和CharDeviceXXXApp”是否存在

输入“depmod”,驱动在第一次执行时,需要运行“depmod”

输入“modprobe CharDeviceXXX.ko”,加载“CharDeviceXXX.ko”模块

输入“lsmod”查看有哪些驱动在工作

输入“mknod /dev/CharDeviceXXX c 200 0回车

//“mknod”是创建节点命令

//“/dev/CharDeviceXXX”表示节点文件

//“c”表示CharDeviceXXX是个字符设备

//“200”表示设备的主设备号

//“0”表示设备的次设备号

输入“ls /dev/CharDeviceXXX  -l回车”,发现节点文件“/dev/CharDeviceXXX

输入“./CharDeviceXXX_APP /dev/CharDeviceXXX 1回车”执行读操作

输入“./CharDeviceXXX_APP /dev/CharDeviceXXX 2回车”执行写操作

输入“cat /proc/devices回车”查询设备号

操作完成,则执行卸载模块:

输入“rmmod CharDeviceXXX.ko”,卸载“CharDeviceXXX.ko”模块

注意:输入“rmmod CharDeviceXXX”也可以卸载“CharDeviceXXX.ko”模块

输入“lsmod”查看有哪些驱动在工作。

至此,CharDeviceXXX设备的整个驱动就验证完成了,驱动工作正常。

8、修改Makefile文件如下:

KERNELDIR := /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31

#使用“:=”将其后面的字符串赋值给KERNELDIR

CURRENT_PATH := $(shell pwd)

#采用“shell pwd”获取当前打开的路径

#使用“$(变量名)”引用“变量的值”

obj-m := CharDeviceXXX.o

#生成“obj-m”需要依赖“CharDeviceXXX.o”

ko: kernel_modules

#生成“build”需要依赖“kernel_modules”

@echo $(KERNELDIR)

#输出KERNELDIR的值为“/home/zgq/linux/atk-mp1/linux/linux-5.4.31”

@echo $(CURRENT_PATH)

#输出CURRENT_PATH的值为/home/zgq/linux/Linux_Drivers/CharDeviceXXX”

@echo $(MAKE)

#输出MAKE的值为make

kernel_modules:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

#后面的"modules"表示编译成模块

#“KERNELDIR”上面定义为“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目录”

#“CURRENT_PATH”上面定义为“当前的工作目录”

#“-C $(KERNELDIR) M=$(CURRENT_PATH) ”表示将“当前的工作目录”切换到“指定的目录”中

#即切换到“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”。

#M表示模块源码目录

#在“make和modules”之间加入“M=$(CURRENT_PATH)”,表示切换到由“CURRENT_PATH”指定的目录中读取源码,同时将其编>译为.ko 文件

clean_ko:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

#“KERNELDIR”上面定义为“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目录”

#“CURRENT_PATH”上面定义为“当前的工作目录

app:

arm-none-linux-gnueabihf-gcc CharDeviceXXX_APP.c -o CharDeviceXXX_APP

clean_app:

rm CharDeviceXXX_APP

9、使用Makefile编译

输入“rm CharDeviceXXX_APP.sh回车

输入“make clean_ko回车”,清除CharDeviceXXX.*

输入“make ko回车”,编译生成CharDeviceXXX.ko

输入“make clean_app回车”,清除CharDeviceXXX_APP

输入“make app回车”,编译生成CharDeviceXXX_APP

输入“ls -l回车

输入“sudo cp CharDeviceXXX.ko CharDeviceXXX_APP /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -f回车

http://www.15wanjia.com/news/3472.html

相关文章:

  • 企业网站四种类型北京seo排名公司
  • dede 网站改宽屏代码便宜的seo官网优化
  • wordpress做淘客网站建网站一般多少钱
  • 大学生个人网站怎么做百度热搜榜
  • 深圳市建设执业培训中心网站网络营销工作内容
  • 做购物网站用什么应用网络营销服务的内容
  • 网站打开速度慢是什么原因搜索关键词技巧
  • 做网站百度推广多少钱品牌网络推广运营公司
  • 今日重大国际新闻军事广西seo优化
  • 如何迅速建企业网站百度应用中心
  • 网站建设技术包括app开发工具哪个好
  • 金蝶云企业云平台谷歌seo搜索
  • 惠阳住房与规划建设局网站便宜的seo网络营销推广
  • 松江网站建设推广应用商店关键词优化
  • 网站策划搭建方案网站的推广方案的内容有哪些
  • 查域名备案信息百度网站排名优化
  • 开淘宝店和做网站有什么区别昆明装饰企业网络推广
  • 重庆网站建设是什么推广衣服的软文
  • 如何在360网页上做公司网站淄博seo网络公司
  • 广州哪里有做网站有必要买优化大师会员吗
  • 南京手机网站建设烟台百度推广公司
  • nas网站怎么做网站百度竞价多少钱一个点击
  • 青岛的网站设计上海seo网站优化软件
  • 化妆品做网站流程成都百度推广开户公司
  • 烟台做网站多钱有域名有服务器怎么做网站
  • 网站备案取名百度一下百度主页官网
  • 要怎么做自己的网站视频教学好搜搜索引擎
  • 网站开发和合同百度下载安装 官方
  • 开网店的流程视频电商关键词排名优化怎么做?
  • 河南郑州汽车网网站建设自学seo能找到工作吗