linux應用開發實例
Ⅰ 嵌入式linux應用層開發有哪些實例
一:c語言 嵌入式Linux工程師的學習需要具備一定的C語言基礎,C語言是嵌入式領域最重要也是最主要的編程語言,通過大量編程實例重點理解C語言的基礎編程以及高級編程知識。包括:基本數據類型、數組、指針、結構體、鏈表、文件操作、隊列、棧等。
二:Linux基礎 Linux操作系統的概念、安裝方法,詳細了解Linux下的目錄結構、基本命令、編輯器VI ,編譯器GCC,調試器GDB和 Make 項目管理工具, Shell Makefile腳本編寫等知識,嵌入式開發環境的搭建。
三:Linux系統編程 重點學習標准I/O庫,Linux多任務編程中的多進程和多線程,以及進程間通信(pipe、FIFO、消息隊列、共享內存、signal、信號量等),同步與互斥對共享資源訪問控制等重要知識,主要提升對Linux應用開發的理解和代碼調試的能力。
四:Linux網路編程 計算機網路在嵌入式Linux系統應用開發過程中使用非常廣泛,通過Linux網路發展、TCP/IP協議、socket編程、TCP網路編程、UDP網路編程、Web編程開發等方面入手,全面了解Linux網路應用程序開發。重點學習網路編程相關API,熟練掌握TCP協議伺服器的編程方法和並發伺服器的實現,了解HTTP協議及其實現方法,熟悉UDP廣播、多播的原理及編程方法,掌握混合C/S架構網路通信系統的設計,熟悉HTML,Javascript等Web編程技術及實現方法。
五:數據結構與演算法 數據結構及演算法在嵌入式底層驅動、通信協議、及各種引擎開發中會得到大量應用,對其掌握的好壞直接影響程序的效率、簡潔及健壯性。此階段的學習要重點理解數據結構與演算法的基礎內容,包括順序表、鏈表、隊列、棧、樹、圖、哈希表、各種查找排序演算法等應用及其C語言實現過程。
六:C++ 、QT C++是Linux應用開發主要語言之一,本階段重點掌握面向對象編程的基本思想以及C++的重要內容。圖形界面編程是嵌入式開發中非常重要的一個環節。由於QT具有跨平台、面向對象、豐富API、支持2D/3D渲染、支持XML、多國語等強大功能,在嵌入式領域的GUI開發中得到了廣范的應用,在本階段通過基於QT圖形庫的學習使學員可以熟練編寫GUI程序,並移植QT應用程序到Cortex-A8平台。包括IDE使用、QT部件及布局管理器、信息與槽機制的應用、滑鼠、鍵盤及繪圖事件處理及文件處理的應用。
七:Cortex A8 、Linux 平台開發 通過基於ARM Cortex-A8處理s5pv210了解晶元手冊的基本閱讀技巧,掌握s5pv210系統資源、時鍾控制器、電源管理、異常中斷控制器、nand flash控制器等模塊,為底層平台搭建做好准備。Linux平台包括內核裁減、內核移植、交叉編譯、GNU工具使用、內核調試、Bootloader介紹、製作與原理分析、根文件系統製作以及向內核中添加自己的模塊,並在s5pv210實驗平台上運行自己製作的Linux系統,集成部署Linux系統整個流程。同時了解Android操作系統開發流程。Android系統是基於Linux平台的開源操作系統,該平台由操作系統、中間件、用戶界面和應用軟體組成,是首個為移動終端打造的真正開放和完整的移動軟體,目前它的應用不再局限於移動終端,還包括數據電視、機頂盒、PDA等消費類電子產品。
八:驅動開發 驅動程序設計是嵌入式Linux開發工作中重要的一部分,也是比較困難的一部分。本階段的學習要熟悉Linux的內核機制、驅動程序與用戶級應用程序的介面,掌握系統對設備的並發操作。熟悉所開發硬體的工作原理,具備ARM硬體介面的基礎知識,熟悉ARM Cortex-A8處理器s5pv210各資源、掌握Linux設備驅動原理框架,熟悉工程中常見Linux高級字元設備、塊設備、網路設備、USB設備等驅動開發,在工作中能獨立勝任底層驅動開發。
以上就是列出的關於一名合格嵌入式Linux開發工程師所必學的理論知識,其實,作為一個嵌入式開發人員,專業知識和項目經驗同樣重要,所以在我們的理論學習中也要有一定的項目實踐,鍛煉自己的項目開發能力。
Ⅱ Linux驅動程序開發實例的目錄
前言
第1章 Linux設備驅動程序模型 1
1.1 設備驅動程序基礎 1
1.1.1 驅動程序的概念 1
1.1.2 驅動程序的載入方式 2
1.1.3 編寫可載入模塊 3
1.1.4 帶參數的可載入模塊 5
1.1.5 設備驅動程序的分類 6
1.2 字元設備驅動程序原理 7
1.2.1 file_operations結構 7
1.2.2 使用register_chrdev注冊字元
設備 9
1.2.3 使用cdev_add注冊字元設備 11
1.2.4 字元設備的讀寫 13
1.2.5 ioctl介面 14
1.2.6 seek介面 16
1.2.7 poll介面 18
1.2.8 非同步通知 22
1.3 proc文件系統 24
1.3.1 proc文件系統概述 24
1.3.2 seq_file機制 25
1.3.3 使用proc文件系統 27
1.4 塊設備驅動程序 32
1.4.1 Linux塊設備驅動程序原理 32
1.4.2 簡單的塊設備驅動程序實例 35
1.5 網路設備驅動程序 39
1.5.1 網路設備的特殊性 39
1.5.2 sk_buff結構 40
1.5.3 Linux網路設備驅動程序架構 42
1.5.4 虛擬網路設備驅動程序實例 46
1.6 Linux 2.6設備管理機制 50
1.6.1 kobject和kset 50
1.6.2 sysfs文件系統 51
1.6.3 設備模型層次 52
1.6.4 platform的概念 54
第2章 Linux內核同步機制 58
2.1 鎖機制 58
2.1.1 自旋鎖 58
2.1.2 讀寫鎖 60
2.1.3 RCU 61
2.2 互斥 64
2.2.1 原子操作 64
2.2.2 信號量 65
2.2.3 讀寫信號量 67
2.3 等待隊列 68
2.3.1 等待隊列原理 68
2.3.2 阻塞式I/O實例 68
2.3.3 完成事件 70
2.4 關閉中斷 71
第3章 內存管理與鏈表 72
3.1 物理地址和虛擬地址 72
3.2 內存分配與釋放 72
3.3 IO埠到虛擬地址的映射 73
3.3.1 靜態映射 73
3.3.2 動態映射 75
3.4 內核空間到用戶空間的映射 76
3.4.1 內核空間到用戶空間的地址
映射原理 76
3.4.2 mmap地址映射實例 78
3.5 內核鏈表 80
3.5.1 Linux內核中的鏈表 80
3.5.2 內核鏈表實例 81
第4章 延遲處理 83
4.1 內核線程 83
4.2 軟中斷機制 85
4.2.1 軟中斷原理 85
4.2.2 tasklet 87
4.3 工作隊列 89
4.3.1 工作隊列原理 89
4.3.2 工作隊列實例 91
4.4 內核時間 92
4.4.1 Linux中的時間概念 92
4.4.2 Linux中的延遲 93
4.4.3 內核定時器 93
第5章 簡單設備驅動程序 96
5.1 寄存器訪問 96
5.1.1 S3C6410地址映射 96
5.1.2 S3C6410看門狗驅動程序實例 98
5.1.3 S3C6410蜂鳴器驅動程序實例 102
5.2 電平控制 107
5.2.1 S3C6410 LED驅動程序實例 107
5.2.2 掃描型S3C6410按鍵驅動
程序實例 109
5.3 時序產生 112
5.3.1 時序圖原理 112
5.3.2 AT24C02晶元原理 112
5.3.3 AT24C02驅動程序開發實例 115
5.4 硬中斷處理 123
5.4.1 硬中斷處理原理 123
5.4.2 中斷型S3C6410按鍵驅動
程序實例 127
5.5 Linux I/O埠控制 132
5.5.1 Linux I/O埠讀寫 132
5.5.2 在應用層訪問Linux I/O
埠 133
5.5.3 /dev/port設備 134
第6章 深入Linux內核 135
6.1 嵌入式Linux系統構成 135
6.2 Linux內核導讀 136
6.2.1 Linux內核組成 136
6.2.2 Linux的代碼結構 137
6.2.3 內核Makefile 138
6.2.4 S3C6410硬體初始化 139
6.3 Linux文件系統 141
6.3.1 虛擬文件系統 141
6.3.2 根文件系統 143
6.3.3 文件系統載入 143
6.3.4 ext3文件系統 145
6.4 Flash文件系統 145
6.4.1 MTD設備 145
6.4.2 MTD字元設備 148
6.4.3 MTD塊設備 150
6.4.4 cramfs文件系統 153
6.4.5 JFFS2文件系統 153
6.4.6 YAFFS文件系統 155
6.4.7 文件系統總結 156
6.5 Linux內核移植 156
6.5.1 體系配置 156
6.5.2 添加yaffs2 157
6.5.3 Nand flash驅動程序移植 157
6.5.4 配置啟動參數 159
6.5.5 移植RTC驅動程序 160
6.6 根文件系統製作 162
6.6.1 Busybox 162
6.6.2 shell基礎 165
6.6.3 根文件系統構建實例 166
6.7 udev模型 167
6.7.1 udev模型原理 167
6.7.2 mdev的使用 167
第7章 I2C匯流排驅動程序 169
7.1 Linux的I2C驅動程序架構 169
7.1.1 I2C適配器 169
7.1.2 I2C演算法 170
7.1.3 I2C驅動程序結構 170
7.1.4 I2C從設備 171
7.1.5 i2c-dev設備層 171
7.2 Linux I2C驅動程序開發 174
7.2.1 S3C2410X的I2C控制器 174
7.2.2 S3C2410X的I2C驅動程序
分析 175
7.3 S3C2410的I2C訪問實例 182
7.4 I2C客戶端驅動程序 185
第8章 TTY與串口驅動程序 190
8.1 TTY概念 190
8.2 Linux TTY驅動程序體系 190
8.2.1 TTY驅動程序調用關系 190
8.2.2 TTY驅動程序原理 191
8.3 線路規程 194
8.4 串口驅動程序與TTY 196
8.4.1 串口設備驅動程序原理 196
8.4.2 S3C6410的串口驅動程序
實例 199
8.5 TTY應用層 202
第9章 網路設備驅動程序 205
9.1 DM9000網卡驅動程序
開發 205
9.1.1 DM9000原理 205
9.1.2 DM9000X驅動程序分析 207
9.1.3 DM9000網口驅動程序移植 215
9.2 NFS根文件系統搭建 219
9.2.1 主機配置 219
9.2.2 NFS根文件系統搭建實例 220
9.3 netlink Socket 224
9.3.1 netlink機制 224
9.3.2 netlink應用層編程 228
9.3.3 netlink驅動程序實例 229
第10章 framebuffer驅動程序 232
10.1 Linux framebuffer驅動
程序原理 232
10.1.1 framebuffer核心數據結構 232
10.1.2 framebuffer操作介面 234
10.1.3 framebuffer驅動程序的文件
介面 236
10.1.4 framebuffer驅動程序框架 236
10.2 S3C6410 顯示控制器 238
10.3 S3C6410 LCD驅動程序實例 243
10.4 framebuffer應用層 250
10.5 Qt4界面系統移植 251
第11章 輸入子系統驅動程序 253
11.1 Linux輸入子系統概述 253
11.1.1 input_dev結構 253
11.1.2 輸入事件 255
11.2 input_handler 256
11.2.1 Input Handler層 256
11.2.2 常用的Input Handler 259
11.3 輸入設備應用層 261
11.4 鍵盤輸入設備驅動程序
實例 262
11.5 event介面 267
11.6 觸摸屏驅動程序實例 270
11.6.1 S3C6410觸摸屏控制器 270
11.6.2 S3C6410觸摸屏驅動程序
設計 273
11.7 觸摸屏校準 282
11.7.1 觸摸屏校準原理 282
11.7.2 利用TSLIB庫校準觸摸屏 282
第12章 USB驅動程序 284
12.1 USB體系概述 284
12.1.1 USB系統組成 284
12.1.2 USB主機 284
12.1.3 USB設備邏輯層次 285
12.2 Linux USB驅動程序體系 287
12.2.1 USB總體結構 287
12.2.2 USB設備驅動程序 287
12.2.3 主機控制器驅動程序 288
12.2.4 USB請求塊urb 289
12.2.5 USB請求塊的填充 291
12.3 S3C6410 USB主機控制器
驅動程序 292
12.3.1 USB主機控制器驅動程序
分析 292
12.3.2 S3C6410 USB驅動程序
載入 294
12.4 USB鍵盤設備驅動程序
分析 296
12.5 USB Gadget驅動程序 301
12.5.1 Linux USB Gadget驅動程序 301
12.5.2 Linux USB Gadget驅動程序
實例 302
第13章 音頻設備驅動程序 303
13.1 ALSA音頻體系 303
13.2 ALSA驅動層API 304
13.2.1 音效卡和設備管理 304
13.2.2 PCM API 304
13.2.3 控制與混音API 305
13.2.4 AC97 API 306
13.2.5 SOC層驅動 307
13.3 ALSA驅動程序實例 308
13.3.1 S3C6410的AC97控制
單元 308
13.3.2 S3C6410音效卡電路原理 309
13.3.3 S3C6410的數字音頻介面 310
13.3.4 wm9713的數字音頻介面 313
13.4 ALSA音頻編程介面 316
13.4.1 ALSA PCM介面實例 316
13.4.2 ALSA MIDI介面實例 320
13.4.3 ALSA mixer介面實例 321
13.4.4 ALSA timer介面實例 322
第14章 video4linux2視頻
驅動程序 327
14.1 video4linux2驅動程序
架構 327
14.1.1 video4linux2驅動程序的
注冊 327
14.1.2 v4l2_fops介面 331
14.1.3 常用的結構 332
14.1.4 video4linux2的ioctl函數 333
14.2 S3C6410攝像頭驅動程序
分析 333
14.2.1 電路原理 333
14.2.2 驅動程序分析 334
14.3 video4linux2應用層實例 339
第15章 SD卡驅動程序 346
15.1 Linux SD卡驅動程序體系 346
15.1.1 SD卡電路原理 346
15.1.2 MMC卡驅動程序架構 347
15.1.3 MMC卡驅動程序相關
結構 347
15.1.4 MMC卡塊設備驅動程序 350
15.1.5 SD卡主機控制器介面驅動
程序 356
15.2 S3C6410 SD卡控制器驅動
程序分析 360
15.2.1 電路原理 360
15.2.2 S3C6410 SDHCI驅動
程序原理 360
15.2.3 SD卡的載入實例 364
參考文獻 366
Ⅲ linux下用c語言編寫區域網聊天工具
/*伺服器*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define SERVPORT 5555
#define BACKLOG 10
#define MAX(a,b) ((a)>(b)?(a):(b))
void str_echo(int);
void server()
{
int sockfd,client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
socklen_t sin_size;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket create error!");
exit(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
perror("bind error!");
exit(1);
}
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen error!");
exit(1);
}
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if((client_fd=accept(sockfd,(struct sockaddr *)&remote_addr,&sin_size))==-1)
{
perror("accept error!");
continue;
}
printf("received a connection from %s\n",inet_ntoa(remote_addr.sin_addr));
if(!fork())
{
close(sockfd);
str_echo(client_fd);
exit(0);
}
close(client_fd);
}
}
void str_echo(int sockfd)
{
int maxfd;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
fd_set rfds;
while(1)
{
FD_SET(0,&rfds);
FD_SET(sockfd,&rfds);
maxfd=MAX(0,sockfd)+1;
select(maxfd,&rfds,NULL,NULL,NULL);
if(FD_ISSET(sockfd,&rfds))
{
bzero(recvbuf,1024);
recv(sockfd,recvbuf,1024,0);
printf("C:%s\n",recvbuf);
}
if(FD_ISSET(0,&rfds))
{
read(0,sendbuf,1024);
send(sockfd,sendbuf,strlen(sendbuf),0);
bzero(sendbuf,1024);
}
}
}
int main()
{
server();
return 0;
}
/*客戶端*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 5555
#define MAXSIZE 1024
#define MAX(a,b) ((a)>(b)?(a):(b))
void client(int argc,char **argv)
{
int sockfd,maxfd;
char sendbuf[MAXSIZE]={0};
char recvbuf[MAXSIZE]={0};
// struct hostent *host;
struct sockaddr_in serv_addr;
fd_set rfds;
/* if(argc<2)
{
fprintf(stderr,"Please enter the sserver's name!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
herror("get host by name error!\n");
exit(1);
}
*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket creat error!\n");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
// serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
bzero(&(serv_addr.sin_zero),8);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connection error!\n");
exit(1);
}
FD_ZERO(&rfds);
while(1)
{
FD_SET(0,&rfds);
FD_SET(sockfd,&rfds);
maxfd=MAX(0,sockfd)+1;
select(maxfd,&rfds,NULL,NULL,NULL);
if(FD_ISSET(sockfd,&rfds))
{
bzero(recvbuf,MAXSIZE);
recv(sockfd,recvbuf,MAXSIZE,0);
printf("S:%s\n",recvbuf);
}
if(FD_ISSET(0,&rfds))
{
fgets(sendbuf,MAXSIZE,stdin);
send(sockfd,sendbuf,strlen(sendbuf),0);
bzero(sendbuf,MAXSIZE);
}
}
// close(sockfd);
}
int main(int argc,char **argv)
{
client(argc,argv);
return 0;
}
Ⅳ 如何編寫驅動程序
代碼:
#include<linux/mole.h>
#include<linux/kernel.h>
#include<asm/io.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
//流水燈代碼
#define GPM4CON 0x110002e0
#define GPM4DAT 0x110002e4
static unsigned long*ledcon=NULL;
static unsigned long*leddat=NULL;
//自定義write文件操作(不自定義的話,內核有默認的一套文件操作函數)
static ssize_t test_write(struct file*filp,const char __user*buff,size_t count,loff_t*offset)
{
int value=0;
int ret=0;
ret=_from_user(&value,buff,4);
//底層驅動只定義基本操作動作,不定義功能
if(value==1)
{
*leddat|=0x0f;
*leddat&=0xfe;
}
if(value==2)
{
*leddat|=0x0f;
*leddat&=0xfd;
}
if(value==3)
{
*leddat|=0x0f;
*leddat&=0xfb;
}
if(value==4)
{
*leddat|=0x0f;
*leddat&=0xf7;
}
return 0;
}
//文件操作結構體初始化
static struct file_operations g_tfops={
.owner=THIS_MODULE,
.write=test_write,
};
//雜設備信息結構體初始化
static struct miscdevice g_tmisc={
.minor=MISC_DYNAMIC_MINOR,
.name="test_led",
.fops=&g_tfops,
};
//驅動入口函數雜設備初始化
static int __init test_misc_init(void)
{
//IO地址空間映射到內核的虛擬地址空間
ledcon=ioremap(GPM4CON,4);
leddat=ioremap(GPM4DAT,4);
//初始化led
*ledcon&=0xffff0000;
*ledcon|=0x00001111;
*leddat|=0x0f;
//雜設備注冊函數
misc_register(&g_tmisc);
return 0;
}
//驅動出口函數
static void __exit test_misc_exit(void)
{
//釋放地址映射
iounmap(ledcon);
iounmap(leddat);
}
//指定模塊的出入口函數
mole_init(test_misc_init);
mole_exit(test_misc_exit);
MODULE_LICENSE("GPL");
(4)linux應用開發實例擴展閱讀:
include用法:
#include命令預處理命令的一種,預處理命令可以將別的源代碼內容插入到所指定的位置;可以標識出只有在特定條件下才會被編譯的某一段程序代碼;可以定義類似標識符功能的宏,在編譯時,預處理器會用別的文本取代該宏。
插入頭文件的內容
#include命令告訴預處理器將指定頭文件的內容插入到預處理器命令的相應位置。有兩種方式可以指定插入頭文件:
1、#include<文件名>
2、#include"文件名"
如果需要包含標准庫頭文件或者實現版本所提供的頭文件,應該使用第一種格式。如下例所示:
#include<math.h>//一些數學函數的原型,以及相關的類型和宏
如果需要包含針對程序所開發的源文件,則應該使用第二種格式。
採用#include命令所插入的文件,通常文件擴展名是.h,文件包括函數原型、宏定義和類型定義。只要使用#include命令,這些定義就可被任何源文件使用。如下例所示:
#include"myproject.h"//用在當前項目中的函數原型、類型定義和宏
你可以在#include命令中使用宏。如果使用宏,該宏的取代結果必須確保生成正確的#include命令。例1展示了這樣的#include命令。
【例1】在#include命令中的宏
#ifdef _DEBUG_
#define MY_HEADER"myProject_dbg.h"
#else
#define MY_HEADER"myProject.h"
#endif
#include MY_HEADER
當上述程序代碼進入預處理時,如果_DEBUG_宏已被定義,那麼預處理器會插入myProject_dbg.h的內容;如果還沒定義,則插入myProject.h的內容。