嵌入式Linux (十三)

姓名:楊喬 ? 學(xué)號:19020100280 ?? 學(xué)院:電子工程學(xué)院

轉(zhuǎn)自:

https://blog.csdn.net/qq_41035588/article/details/92002740

【嵌牛導(dǎo)讀】嵌入式一般指嵌入式系統(tǒng)。嵌入式系統(tǒng)由硬件和軟件組成。是能夠獨立進行運作的器件。Linux,全稱GNU/Linux,是一種免費使用和自由傳播的類UNIX操作系統(tǒng),其內(nèi)核由林納斯·本納第克特·托瓦茲于1991年10月5日首次發(fā)布,它主要受到Minix和Unix思想的啟發(fā),是一個基于POSIX的多用戶、多任務(wù)、支持多線程和多CPU的操作系統(tǒng)。

【嵌牛鼻子】基于ARM的嵌入式Linux開發(fā)總結(jié)

【嵌牛提問】基于ARM的嵌入式Linux開發(fā)如何使用?

【嵌牛正文】

一、Linux進程編程

進程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是操作系統(tǒng)進行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。

1 進程控制

?子進程創(chuàng)建:fork()函數(shù)

在Linux中創(chuàng)建一個新進程的唯一方法是使用fork()函數(shù)。fork()函數(shù)是Linux中一個非常重要的函數(shù),和以往遇到的函數(shù)有一些區(qū)別,因為fork()函數(shù)看起來執(zhí)行一次卻返回兩個值。

1)fork()函數(shù)說明

fork()函數(shù)用于從已存在的進程中創(chuàng)建一個新進程。新進程稱為子進程,而原進程稱為父進程。

使用fork()函數(shù)得到的子進程是父進程的一個復(fù)制品,它從父進程處繼承了整個進程的地址空間,包括進程的上下文、代碼段、進程堆棧、內(nèi)存信息、打開的文件描述符、符號控制設(shè)定、進程優(yōu)先級、進程組號、當(dāng)前工作目錄、根目錄、資源限制和控制終端等,而子進程所獨有的只有它的進程號、資源使用和計時器等。

因為子進程幾乎是父進程的完全復(fù)制,所以父子兩進程會運行同一個程序。這就需要用一種方式來區(qū)分它們,并使它們照此運行,否則,這兩個進程不可能做不同的事。

實際上是在父進程中執(zhí)行fork()函數(shù)時,父進程會復(fù)制一個子進程,而且父子進程的代碼從fork()函數(shù)的返回開始分別在兩個地址空間中同時運行,從而使兩個進程分別獲得所屬fork()函數(shù)的返回值,其中在父進程中的返回值是子進程的進程號,而在子進程中返回0。因此,可以通過返回值來判斷該進程的父進程還是子進程。

2)fork()函數(shù)語法

?進程等待函數(shù)

1)wait()函數(shù),無條件等待,父進程阻塞直到子進程結(jié)束

2)waitpid()函數(shù),指定等待某個子進程結(jié)束以及等待的方式(阻塞或非阻塞)

所需頭文件 #include <sys/types.h>

#include <sys/wait.h>

函數(shù)原型 pid_t waitpid(pid_t pid, int *status, int options)

函數(shù)參數(shù) pid pid>0:只等待進程ID等于pid的子進程,不管已經(jīng)有其他子進程運行結(jié)束退出了,只要指定的子進程還沒有結(jié)束,waitpid就會一直等下去。

pid=-1:等待任何一個子進程退出,此時和wait作用一樣。

pid=0:等待其組ID等于調(diào)用進程的組ID的任一子進程。

pid<-1:等待其組ID等于pid的絕對值的任一子進程。

status 同wait

options WNOHANG:若由pid指定的子進程并不立即可用,則waitpid不阻塞,此時返回值為0

WUNTRACED:若某實現(xiàn)支持作業(yè)控制,則由pid指定的任一子進程狀態(tài)已暫停,且其狀態(tài)自暫停以來還未報告過,則返回其狀態(tài)。

0:同wait,阻塞父進程,等待子進程退出。

函數(shù)返回值 正常:結(jié)束的子進程的進程號

使用選項WNOHANG且沒有子進程結(jié)束時:0

調(diào)用出錯:-1

所需頭文件 #include <sys/types.h>

#include <sys/wait.h>

函數(shù)原型 pid_t waitpid(pid_t pid, int *status, int options)

函數(shù)參數(shù) pid pid>0:只等待進程ID等于pid的子進程,不管已經(jīng)有其他子進程運行結(jié)束退出了,只要指定的子進程還沒有結(jié)束,waitpid就會一直等下去。

pid=-1:等待任何一個子進程退出,此時和wait作用一樣。

pid=0:等待其組ID等于調(diào)用進程的組ID的任一子進程。

pid<-1:等待其組ID等于pid的絕對值的任一子進程。

status 同wait

options WNOHANG:若由pid指定的子進程并不立即可用,則waitpid不阻塞,此時返回值為0

WUNTRACED:若某實現(xiàn)支持作業(yè)控制,則由pid指定的任一子進程狀態(tài)已暫停,且其狀態(tài)自暫停以來還未報告過,則返回其狀態(tài)。

0:同wait,阻塞父進程,等待子進程退出。

函數(shù)返回值 正常:結(jié)束的子進程的進程號

使用選項WNOHANG且沒有子進程結(jié)束時:0

調(diào)用出錯:-1

?進程結(jié)束:exit()和_exit()

所需頭文件 exit:#include <stdlib.h>

_exit:#include <unistd.h>

函數(shù)原型 exit:void exit(int status);

_exit:void _exit(int status);

函數(shù)傳入值 status是一個整型的參數(shù),可以利用這個參數(shù)傳遞進程結(jié)束時的狀態(tài)。

通常0表示正常結(jié)束;其他的數(shù)值表示出現(xiàn)了錯誤,進程非正常結(jié)束。

在實際編程時,可以用wait系統(tǒng)調(diào)用接收子進程的返回值,進行相應(yīng)的

處理。

所需頭文件 exit:#include <stdlib.h>

_exit:#include <unistd.h>

函數(shù)原型 exit:void exit(int status);

_exit:void _exit(int status);

函數(shù)傳入值 status是一個整型的參數(shù),可以利用這個參數(shù)傳遞進程結(jié)束時的狀態(tài)。

通常0表示正常結(jié)束;其他的數(shù)值表示出現(xiàn)了錯誤,進程非正常結(jié)束。

在實際編程時,可以用wait系統(tǒng)調(diào)用接收子進程的返回值,進行相應(yīng)的

處理。

兩者的區(qū)別:

(1)_exit()函數(shù)的作用最為簡單:直接使進程終止運行,清除其使用的內(nèi)存空間,并銷毀其在內(nèi)核中的各種數(shù)據(jù)結(jié)構(gòu);

(2)exit()函數(shù)則在這些基礎(chǔ)上作了一些包裝,在執(zhí)行退出之前加了若干道工序。

(3)exit()函數(shù)在調(diào)用exit系統(tǒng)調(diào)用之前要檢查文件的打開情況,把文件緩沖區(qū)中的內(nèi)容寫回文件,就是"清理I/O緩沖"。

?Linux下的進程間通信

進程間通信用于實現(xiàn)參數(shù)傳遞及通信功能;Linux支持的常用的進程間通信方法:管道、消息隊列、共享內(nèi)存、信號量、套接口等等。

實例:(1)實驗三:Linux進程編程;

(2)網(wǎng)盤linux編程源代碼目錄下fork文件下相關(guān)實例(FIFO、msgque、shm)。

嵌入式知識點復(fù)習(xí)六 --arm-linux網(wǎng)絡(luò)編程

1、程序流程

(1)網(wǎng)絡(luò)通信程序架構(gòu)-客戶端/服務(wù)器架構(gòu)

2、函數(shù)說明

?socket()

Sockfd=socket(AF_INET,SOCK_STREAM,0);

?Bind()

s_add.sin_family=AF_INET;IPV4協(xié)議

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()服務(wù)器端偵聽函數(shù)

listen(Sockfd,5)服務(wù)器偵聽來自客戶端的請求

?accept()服務(wù)器端接受客戶端連接請求

nfp = accept(Sockfd, (struct sockaddr *)(&c_add), sizeof(struct sockaddr);

?send()數(shù)據(jù)發(fā)送函數(shù)

send(nfp,“hello,welcome to my server”,32,0)

?recv()數(shù)據(jù)接收函數(shù)

recv(nfp,buffer,1024,0)

?關(guān)閉連接

Close(nfp)

?關(guān)閉服務(wù)器

Close(Sockfd)

實例:(1)實驗四:網(wǎng)絡(luò)聊天室設(shè)計

(2)網(wǎng)盤/linux編程源代碼/socket下相關(guān)代碼

嵌入式知識點復(fù)習(xí)七 --linux字符型設(shè)備驅(qū)動初步

一、Linux字符設(shè)備驅(qū)動初步

1、Linux設(shè)備類型

(1)字符設(shè)備:只能一個字節(jié)一個字節(jié)的讀寫的設(shè)備,不能隨機讀取設(shè)備內(nèi)存中的某一數(shù)據(jù),讀取數(shù)據(jù)需要按照先后順序進行。字符設(shè)備是面向流的設(shè)備,常見的字符設(shè)備如鼠標(biāo)、鍵盤、串口、控制臺、LED等。

(2)塊設(shè)備:是指可以從設(shè)備的任意位置讀取一定長度的數(shù)據(jù)設(shè)備。塊設(shè)備如硬盤、磁盤、U盤和SD卡等存儲設(shè)備。

(3)網(wǎng)絡(luò)設(shè)備:網(wǎng)絡(luò)設(shè)備比較特殊,不在是對文件進行操作,而是由專門的網(wǎng)絡(luò)接口來實現(xiàn)。應(yīng)用程序不能直接訪問網(wǎng)絡(luò)設(shè)備驅(qū)動程序。在/dev目錄下也沒有文件來表示網(wǎng)絡(luò)設(shè)備。

2、開發(fā)流程

3、關(guān)鍵函數(shù)講解(以2.6以下版本內(nèi)核為例)

(1)驅(qū)動模塊注冊register_chrdev()函數(shù)

原型:register_chrdev(unsigned int major, const char *name,const struct file_operations *fops);

major:主設(shè)備號,該值為 0 時,自動運行分配。而實際值不是 0 ;

name:設(shè)備名稱;

fops:操作函數(shù),實現(xiàn)驅(qū)動定義的open、read、write、close等內(nèi)核函數(shù)與應(yīng)用程序調(diào)用的open、read、write、close間的映射;

返回值:

major 值為 0 ,正常注冊后,返回分配的主設(shè)備號。如果分配失敗,返回 EBUSY 的負值 ( -EBUSY ) 。major 值若大于 linux/major.h (2.4內(nèi)核)中聲明的最大值 (#define MAX_CHRDEV 255) ,則返回EINVAL 的負值 (-EINVAL) 。指定 major 值后,若有注冊的設(shè)備,返回 EBUSY 的負值 (-EBUSY)。若正常注冊,則返回 0 值

(2)驅(qū)動注銷unregister_chrdev()函數(shù)

原型:

#include <linux.fs.h>

int unregister_chrdev (unsigned int major, const char *name)

變量:

?major 主設(shè)備號

?name 設(shè)備文件

返回值:

major 值若大于 linux/major.h (2.4 內(nèi)核)中聲明的最大值 (#define MAX_CHRDEV 255),返回 EINVAL的負值 (-EINVAL)。指定了 major的值后,若將要注銷的 major 值并不是注冊的設(shè)備驅(qū)動程序,返回 EINVAL的負值 ( -EINVAL )。正常注銷則返回 0值。

(3)File_operation結(jié)構(gòu)體

file_operations結(jié)構(gòu)是建立驅(qū)動程序和設(shè)備編號的連接,內(nèi)部是一組函數(shù)指針,每個打開的文件,也就是file結(jié)構(gòu),和一組函數(shù)關(guān)聯(lián),這些操作主要用來實現(xiàn)系統(tǒng)調(diào)用的

struct file_operations {

  struct module *owner;//擁有該結(jié)構(gòu)的模塊的指針,一般為THIS_MODULES

loff_t (*llseek) (struct file *, loff_t, int);//用來修改文件當(dāng)前的讀寫位置

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//從設(shè)備中同步讀取數(shù)據(jù)

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//向設(shè)備發(fā)送數(shù)據(jù)

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);//僅用于讀取目錄,對于設(shè)備文件,該字段為NULL

unsigned int (*poll) (struct file *, struct poll_table_struct *); //輪詢函數(shù),判斷目前是否可以進行非阻塞的讀寫或?qū)懭?/p>

  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //執(zhí)行設(shè)備I/O控制命令

  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系統(tǒng),將使用此種函數(shù)指針代替ioctl

  long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系統(tǒng)上,32位的ioctl調(diào)用將使用此函數(shù)指針代替

  int (*mmap) (struct file *, struct vm_area_struct *); //用于請求將設(shè)備內(nèi)存映射到進程地址空間

  int (*open) (struct inode *, struct file *); //打開

  int (*flush) (struct file *, fl_owner_t id);

  int (*release) (struct inode *, struct file *); //關(guān)閉

  int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待處理的數(shù)據(jù)

  int (*aio_fsync) (struct kiocb *, int datasync); //異步刷新待處理的數(shù)據(jù)

  int (*fasync) (int, struct file *, int); //通知設(shè)備FASYNC標(biāo)志發(fā)生變化

  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 **);

};

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容