程式算法本身的複雜度
CPU的速度和設計架構
CPU的位元帶寬
自己的程式的寫法
程式算法本身的複雜度
CPU的速度和設計架構
CPU的位元帶寬
自己的程式的寫法
.png)
1.鳥哥私房菜 第十六章、檔案伺服器之二: SAMBA 伺服器 http://linux.vbird.org/linux_server/0370samba.php#theory_source
資料來源: https://fredwang.blogspot.com/2013/05/sambalinuxwindows.html
Linux mount the samba disk
mount -t cifs -o username=guest,password="" //192.168.1.183/share /home/usb
本篇介紹如何使用 Linux 的 grep 指令,根據關鍵字或正規表示法找出想要的資料。
Linux 的 grep 是一個很好用的指令,可以從串流資料或檔案中,使用關鍵字或正規表示法(regular expression)篩選出想要尋找的資料,並且顯示出來,以下是 grep 的用法教學以及實際範例。
grep 這個指令名稱其實是來自於正規表示法的 g/RE/p,其意義是代表以正規表示法全域搜尋並列印出來(globally search for RE and print it)。
grep 最基本的用法就是以普通的關鍵字來搜尋,其基本語法如下:
grep 關鍵字 檔案1 檔案2 ...
例如在 /etc/os-release 檔案中搜尋 Ubuntu 關鍵字:
grep Ubuntu /etc/os-release
NAME="Ubuntu" PRETTY_NAME="Ubuntu 18.04.3 LTS"
執行的結果會列出所有含有關鍵字的整行文字。
grep 亦可搭配萬用字元(*)同時搜尋多個檔案,例如在 /etc/ 目錄之下所有 *.conf 檔案中,尋找 network 這個字眼:
grep network /etc/*.conf
ltrace.conf:hex(uint) inet_network(string); nsswitch.conf:networks: files sysctl.conf:# Additional settings - these settings can improve the network sysctl.conf:# security of the host and prevent against some network attacks sysctl.conf:# redirection. Some network environments, however, require that these
搜尋多個檔案時,在輸出中會標示資料來源是哪一個檔案。
除了搜尋檔案內容之外,亦可搭配管線(pipe)篩選串流資料,例如篩選出含有 network 關鍵字的檔案名稱:
ls /etc/ | grep network
network networkd-dispatcher networks
grep 預設會區分字母的大小寫,如果希望以不分大小寫的方式搜尋,可以加上 -i 參數:
grep -i Ubuntu /etc/os-release若要標示匹配文字的行號,可以加上 -n 參數:
grep -n Ubuntu /etc/os-release1:NAME="Ubuntu" 5:PRETTY_NAME="Ubuntu 18.04.3 LTS"
若想要將匹配的資料排除,只顯示出沒有關鍵字的那幾行資料,可以加上 -v 參數。例如顯示不包含 Ubuntu 關鍵字的那幾行:
grep -v Ubuntu /etc/os-release如果想要在指定目錄與其子目錄下所有的檔案中,搜尋指定的關鍵字,可以加上 -r 參數:
grep -r ubuntu /etc/如果只想要從特定的檔案中尋找關鍵字,可以使用 -r 搭配 --include 指定檔案類型:
grep -r --include="*.conf" ubuntu /etc/
如果自己的權限沒辦法讀取所有的檔案,就會出現某些檔案無法讀取的錯誤訊息,這時候可以將這種錯誤訊息導向 /dev/null,只看正常訊息就好:
grep -r ubuntu /etc/ 2>/dev/null
有時候只顯示匹配成功那一行,不容易看出是否是我們想要找的資料,這時候可以加上 -A(After)、-B(Before)或-C(Context),指定要顯示的前後行數:
grep -A 1 Ubuntu /etc/os-release grep -B 1 Ubuntu /etc/os-release grep -C 1 Ubuntu /etc/os-release
grep 可以使用顏色標示的方式,將成功匹配的部分文字標示出來,方便使用者閱讀。顏色標示功能可以透過 --color=never、--color=always、--color=auto 這幾種參數來關閉、開啟或設為自動。開啟顏色標示的輸出會像這樣:
grep 在搜尋關鍵字時,其實是以正規表示法的方式匹配文字的,所以一般的正規表示法都可以直接使用,以下是一些常用的範例。開頭與結尾是最常用的:
ls | grep "^a" ls | grep "b$" ls | grep "^[ab]" ls | grep "[ab]$"
各種出現次數的指定:
ls | grep "^ab*" ls | grep "^ab?" ls | grep "^ab+"
多種字眼的組合,也很常用:
ls | grep "ab|cd" ls | grep -E "ab|cd"
如果只想要精準篩選出 net 這個單字,可以這樣寫:
ls | grep "<net>"
issue.net
這樣就只會出現含有 net 這一個單字的結果,像是 network 這樣的字眼就會被排除。
參考資料:鳥哥的 Linux 私房菜、Carlos-Studio、Linux 命令大全
資料來源: https://blog.gtwang.org/linux/linux-grep-command-tutorial-examples/
在這個單元,我們要開始運用 udev 呼叫 my_script 的時候,所傳過來的環境變數(environment variables)。其中最重要,而且每次都一定會設定的變數就是:SUBSYSTEM 及 ACTION。其他的許多變數常因 SUBSYSTEM 而異。
在第一個單元裡,我們曾寫了一個範例程式,叫做 my_script,讓 Linux 系統每次發生 udev 事件時,都會發出一次聲響(sound effect)。以一個 USB thumb drive 做實驗,插入(insert)或拔除(unplug)時分別都會聽見約 6、7 次,以及 3 次聲響。也就是說,插入一個 USB 隨身碟時,系統上會產生許多次的 uevents。拔除時亦然。我們再複習一下這個簡單的掛勾機制(hook):
$ cat /etc/udev/rules.d/z99_test.rules
RUN+="/home/nobody/my_script"
$ ls -l ~/my_script
-rwxr-xr-x 1 nobody nobody 1056 Nov 22 03:04 /home/nobody/my_script
為了篩選出(match)方便與之掛勾的特定事件(uevent),我們必須更進一步追蹤這些事件的內幕。首先,把 my_script 改寫為以下 3 行:
#!/bin/sh
echo $SEQNUM $SUBSYSTEM $ACTION $DEVNAME >> /tmp/my_script.log
exit $?
先以 root 的權限把 logfile /tmp/my_script.log 的內容清空,再插入,或拔除手邊任何一個 USB 隨身碟。然後再看看在 /tmp/my_script.log 這個檔案裡面,我們到底收集到了那些情資。結果大概會很接近如下所示的內容:
2124 usb add /dev/1-6
2125 usb add
2126 scsi_host add
2127 usb_device add /dev/bus/usb/001/007
2134 bdi add
2128 scsi add
2129 scsi_disk add
2131 scsi change
2130 scsi_device add
2132 block add /dev/sda
2133 block add /dev/sda1
2136 scsi_disk remove
2135 scsi_device remove
2137 block remove /dev/sda1
2140 scsi remove
2143 usb_device remove /dev/bus/usb/001/007
2138 bdi remove
2141 scsi_host remove
2142 usb remove
2139 block remove /dev/sda
2144 usb remove /dev/1-6
其中第一個 field 是環境變數 SEQNUM 的值,可用來判別事件發生的先後順序,第二個是 SUBSYSTEM,第三個是 ACTION,第四個則為 DEVNAME 的值,其中,DEVNAME 有時候並未設定。細數後可知,插入 USB 的動作導致系統上一共產生了 11 次的 uevents,拔除時,則產生了 10 次的 uevents。在這眾多的 uevents 當中,特別適合用來唯一識別 USB 裝置插入(insert)及拔除(remove)動作的事件,也就是只發生過一次的事件可說是:
SUBSYSTEM==usb_device
ACTION==add
以及
SUBSYSTEM==usb_device
ACTION==remove
以下這個 my_script 示範如何限縮這個 script 的反應,只在插入或移除一個 USB device 時發出聲響,而且分別只響一次:
#!/bin/sh
# my_script example 3-1
LOGFILE=/tmp/my_script.log # 定義變數 LOGFILE
exec 3>> $LOGFILE && exec >& 3 && exec 2>&1 # 把 stdout/stderr 導入 $LOGFILE
SND_USB_INSERT="/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav" # 定義聲音檔
SND_USB_REMOVE="/xp/WINDOWS/Media/chimes.wav" # 定義聲音檔
if [ "$SUBSYSTEM" = "usb_device" -a "$ACTION" = "add" ]
then
echo ""
echo "=============================="
date "+%G-%m-%dT%H:%M:%S %z"
echo "$SUBSYSTEM $ACTION"
echo "aplay -q \"$SND_USB_INSERT\""
aplay -q "$SND_USB_INSERT"
elif [ "$SUBSYSTEM" = "usb_device" -a "$ACTION" = "remove" ]
then
echo ""
echo "=============================="
date "+%G-%m-%dT%H:%M:%S %z"
echo "$SUBSYSTEM $ACTION"
echo "aplay -q \"$SND_USB_REMOVE\""
aplay -q "$SND_USB_REMOVE"
fi
exit $?
編輯 my_script 的時候,要確認聲音檔是不是存在。編輯完畢之後,要記得做
$ chmod 755 ~/my_script
以上的 script 是說,當(if) SUBSYSTEM 這個變數的值等於(=)usb_device,而且(-a)當 變數 ACTION 的值為 add 的時候,就(then)執行一些 echo(1), date(1), aplay(1) 的指令;要不然的話當(elif)變數 SUBSYSTEM 的值為(=) usb_device,而且(-a)變數 ACTION 的值為(=)remove 時,就(then)執行另一批指令。請注意,方括號 [ 及 ] 跟 = 的前後,要有空白(space),變數(variable)的前後,也必須加上雙引號(double quotation marks),因為變數值可能會包含空白字元(embedded spaces)。
最後一個指令 "exit $?",是要結束這個 script 並把當時的執行結果傳回(return)給呼叫這個 script 的任何程式。想要省略掉的話,也沒什麼問題,然而我們必須平時就養成撰寫程式的正確習慣,在 UNIX 系統上,任何程式、函式都必須要有傳回值,就算是不知道有誰會去用它。我們不希望看到那一天,當有人突然去用它的時候,就必須面對噩運。這看似小事一件,然而缺乏持續性對小節的正確習慣或態度,我們對核四的運轉,為了自己的生存,必須反對到底。
做完以上的 script,只要隨手找個 USB 設備插入,或拔出,就都會聽到變數 $SND_USB_INSERT 或是 $SND_USB_REMOVE 所設定的聲效檔(sound file)。這是採用正面表列只當變數 SUBSYSTEM 內傳過來的值為 usb_device 時,才依變數 ACTION 的值是 add 或是 remove 來採取行動。
如果我們也希望這個程式對記憶卡以及 PCMCIA、CF 以及 SD 插槽也有所反應的話,則可修改程式,也檢查變數 SUBSYSTEM 是否為 "mmc" 或是 "pcmcia"。以同樣的方法可以得知,SD 卡插槽,以及 PCMCIA 插槽的插入與拔除動作可以:
SUBSYSTEM==mmc
ACTION==addSUBSYSTEM==mmc
ACTION==removeSUBSYSTEM==pcmcia
ACTION==addSUBSYSTEM==pcmcia
ACTION==remove
可靠地識別。以下的另一個 my_script 範例則示範採用負面表列的邏輯結構,檢查變數 SUBSYSTEM 如果不是 "usb_device"、"mmc"、"pcmcia" 其中之一的話,即立刻結束程式(terminate),不然,則印出訊息,再判斷變數 ACTION 為 "add" 或 "remove" 分別作出對應的音效:
#!/bin/sh
# my_script example 3-2
LOGFILE=/tmp/my_script.log # 定義變數 LOGFILE
exec 3>> $LOGFILE && exec >& 3 && exec 2>&1 # redirect stdout/stderr 到 LOGFILE
SND_INSERT="/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav" # 定義聲音檔
SND_REMOVE="/xp/WINDOWS/Media/chimes.wav" # 定義聲音檔
if [ "$SUBSYSTEM" != "usb_device" -a "$SUBSYSTEM" != "pcmcia" -a "$SUBSYSTEM" != "mmc" ]
then
exit 0
fi
echo ""
echo "=============================="
date "+%G-%m-%dT%H:%M:%S %z"
echo "$SUBSYSTEM $ACTION"
if [ "$ACTION" = "add" ]
then
echo "aplay -q \"$SND_INSERT\""
aplay -q "$SND_INSERT"
elif [ "$ACTION" = "remove" ]
then
echo "aplay -q \"$SND_REMOVE\""
aplay -q "$SND_REMOVE"
fi
exit $?
編輯完畢、儲存檔案後,程式會立即生效。這時,無論是在 PCMCIA 插槽、CF 插槽、SD 插槽,還是 USB 插座插入或拔除週邊設備,電腦都會發出預設的音效,而且每個動作只會發出一次聲音,不像在第一單元那樣發出 6、7 次的聲響。
變數 ACTION 除了 "add" 跟 "remove" 兩個可能的值以外,還可能會是 "change"。這例如可能會發生於以下的情況:如果你使用的是一台含有內建電池的筆記型電腦(notebooks),那麼,在插上或拔掉外接電源線(AC power cord)時,udev 系統分別會產生兩種 uevents:
SUBSYSTEM=power_supply
ACTION=change
POWER_SUPPLY_ONLINE=1
以及
SUBSYSTEM=power_supply
ACTION=change
POWER_SUPPLY_ONLINE=0
我們現在就繼續改良以上的 my_script,讓它在插入跟拔掉電源線時,也會發出聲音信號:
#!/bin/sh
# my_script example 3-3
LOGFILE=/tmp/my_script.log # 定義變數 LOGFILE
exec 3>> $LOGFILE && exec >& 3 && exec 2>&1 # redirect stdout/stderr 到 LOGFILE
SND_INSERT="/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav" # 定義聲音檔
SND_REMOVE="/xp/WINDOWS/Media/chimes.wav" # 定義聲音檔
PRINT_DATE()
{
echo ""
echo "=============================="
date "+%G-%m-%dT%H:%M:%S %z"
}
if [ "$SUBSYSTEM" != "usb_device" -a "$SUBSYSTEM" != "pcmcia" -a "$SUBSYSTEM" != "mmc" -a "$SUBSYSTEM" != "power_supply" ]
then
exit 0
fi
if [ "$SUBSYSTEM" = "power_supply" -a "$ACTION" = "change" ]
then
if [ "$POWER_SUPPLY_ONLINE" = "0" ]
then
PRINT_DATE
echo "$SUBSYSTEM $ACTION OFFLINE"
echo "aplay -q \"$SND_REMOVE\""
aplay -q "$SND_REMOVE"
elif [ "$POWER_SUPPLY_ONLINE" = "1" ]
then
PRINT_DATE
echo "$SUBSYSTEM $ACTION ONLINE"
echo "aplay -q \"$SND_INSERT\""
aplay -q "$SND_INSERT"
fi
else
if [ "$ACTION" = "add" ]
then
PRINT_DATE
echo "$SUBSYSTEM $ACTION"
echo "aplay -q \"$SND_INSERT\""
aplay -q "$SND_INSERT"
elif [ "$ACTION" = "remove" ]
then
PRINT_DATE
echo "$SUBSYSTEM $ACTION"
echo "aplay -q \"$SND_REMOVE\""
aplay -q "$SND_REMOVE"
fi
fi
exit $?
這個第三個版本,我們在程式的前面,定義了一個函數叫做 "PRINT_DATE ()",它是用來避免重複的程式碼(repeated codes),使得程式比較簡短易讀(readability)。
還記得我們把這個程式的所有 stdout 以及 stderr 都導向 $LOGFILE 了嗎?在指令行打:
$ less /tmp/my_script.log
則會看到類似以下的文字紀錄(logs):
==============================
2011-11-11T05:02:52 +0800
pcmcia add
aplay -q "/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav"
==============================
2011-11-11T05:03:01 +0800
pcmcia remove
aplay -q "/xp/WINDOWS/Media/chimes.wav"
==============================
2011-11-11T05:03:16 +0800
mmc add
aplay -q "/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav"
==============================
2011-11-11T05:03:23 +0800
mmc remove
aplay -q "/xp/WINDOWS/Media/chimes.wav"
==============================
2011-11-11T07:24:26 +0800
power_supply change OFFLINE
aplay -q "/xp/WINDOWS/Media/chimes.wav"
==============================
2011-11-11T07:24:29 +0800
power_supply change ONLINE
aplay -q "/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav"
==============================
2011-11-11T05:05:18 +0800
usb_device add
aplay -q "/xp/WINDOWS/Media/Windows XP Pop-up Blocked.wav"
==============================
2011-11-11T05:05:46 +0800
usb_device remove
aplay -q "/xp/WINDOWS/Media/chimes.wav"
資料來源: http://kolmogolovi.blogspot.com/2011/11/linux-udev-3.html
刪除整個RAID:
mdadm / dev / md0–fail / dev / sdb–remove / dev / sdb
mdadm / dev / md0–fail / dev / sdc–remove / dev / sdc
mdadm / dev / md0–fail / dev / sdc–remove / dev / sdd
mdadm / dev / md0–失敗/ dev / sde–刪除/ dev / sde
mdadm / dev / md0–失敗/ dev / sdf–刪除/ dev / sdf
mdadm–stop / dev / md0
mdadm–remove / dev / md0
mdadm–misc–zero-superblock / dev / sdb
mdadm–misc–zero-superblock / dev / sdc
mdadm–misc–zero-superblock / dev / sdd
mdadm–misc–zero-superblock / dev / sde
mdadm–misc–zero-超級塊/ dev / sdf
即:先刪除RAID中的所有設備,然後停止該RAID即可
為了防止系統啟動時候啟動raid
rm-f/etc/mdadm.conf
rm-f/etc/raidtab
檢查系統啟動文件中是否還有其他mdad啟動方式
vi/etc/rc.sysinit+/raid\c
資料來源: http://www.4u.idv.tw/2018/09/14/mdadm%E8%BD%AFraid%E7%9A%84%E5%88%A0%E9%99%A4%E6%96%B9%E6%B3%95%E5%92%8C%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/
Objective: This writeup will cover WiFi configuration on Raspberry Pi using the Yocto tool. The goal is to have an automatic WiFi connection on boot-up
Recommended prerequisite articles to read:
In the previous article, we built a console-only image for the Raspberry Pi 4. For such a headless set up, we need a smooth way to interact with the device. One of the most convenient way is the use of the SSH protocol that can allow us to remotely access the raspberry pi and even transfer files to it via scp. However, to use these tools the board and the host machine need to be connected in a way such as being in the same local network or connected to the internet. Hence to connect the Pi to the internet, we need to enable the WiFi.
We don’t want to be manually configuring the WiFi every time a reboot occurs. At the time being, we can assign a static IP address to our board since this is for in-house development. We will also hard code the router/network SSID and our password. All these can be performed after bootup but we want to have all the network configurations performed automatically at boot up.
1. Configure SSID and passphrase
Edit the wpa_supplicant.conf-sane in the following path … /meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant.conf-sane
ctrl_interface = /var/run/wpa_supplicantctrl_interface_group = 0update_config = 1Network = { ssid = "SSID" psk = "PASSWD"} |
2 . Script to initialize the wpa_supplicant and configure WiFi at boot up
Create a custom script “setup-wifi.sh” at the following path …/meta/recipes-core/initscripts/initscripts-1.0/setup-wifi.sh
#!/bin/shifconfig wlan0 10.233.174.16 #Set the static IP address, should be uniquewpa_passphrase SSID PASSWD> /etc/wpa_supplicant.confroute add default gw 10.233.174.254 #Router IP addresswpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.confecho “nameserver 8.8.8.8” >> /etc/resolv.confecho “nameserver 10.233.174.254” >> /etc/resolv.conf: exit 0 |
3. Edit initscript recipe to enable WiFi configuration at boot up
Edit the initscript bitbake recipe at … /meta/recipes-core/initscripts/initscripts-1.0.bb that incorporates the “setup-wifi.sh” and installs it in /etc/initscripts directory after build.
SRC_URI = "file://setup-wifi.sh \"do_install () {install -m 0755 ${WORKDIR}/setup-wifi.sh ${D}${sysconfdir}/init.d update-rc.d -r ${D} setup-wifi.sh start 99 2 3 4 5 .} MASKED_SCRIPTS = " \setup-wifi \" |
SSH
With the above configurations, rebuild the core-image as explained in the previous article. On bootup, you can test the WiFi configuration by issuing the commands:
ifconfig //should show the IP address of the Pi as hard coded in the Yocto imageping google.com //shows that the DNS server(s) hardcoded are working |
With the above network configurations, we can access the board remotely via ssh and transfer files via scp from a Linux machine.
On the Linux machine, we enter the IP address we assigned to the board as below:
This opens a terminal console of the board remotely and we can access all the files remotely.
資料來源: https://reiwaembedded.com/raspberry-pi-yocto-wifi-configuration-for-automatic-connection-at-boot/