Linux下系統函式
Linux下系統函式
rand()函式
獲取02147483647(0RAND_MAX)之間的隨機數。真隨機需要srand()設定種子。一般用時間作為srand()的引數
#include<unistd.h>
int rand(void)
void srand(unsigned int seed)
字元函式
標頭檔案<ctype.h>
函式名 | 功能 |
---|---|
isalnum | 測試字元是否為英文或數字 |
isalpha | 測試是否為英文字母 |
isascii | 測試是否為ascii字元 |
iscntrl | 測試是否為ascii控制字元 |
isdigit | 測試是否為阿拉伯數字 |
islower | 測試是否為小寫字母 |
isprint | 測試是否可列印字元 |
isspace | 測試是否空格字元 |
ispunct | 測試是否為標點或特殊符號 |
isupper | 測試是否大寫字母 |
isxdigit | 測試是否16進位制數字 |
系統時間和日期函式
函式名 | 功能 |
---|---|
asctime | 將時間和日期以字串的格式表示 |
ctime | 將時間和日期以字串的格式表示 |
gettimeofday | 獲得當前時間 |
gmtime | 把時間或日期轉為GTM時間 |
localtime | 獲得目前當地的時間和日期 |
mktime | 將時間結構資料轉換為經過的秒數 |
settimeofday | 設定當前時間 |
time | 取得系統當前時間 |
#include<time.h>
//成功返回秒數,並將結果存入t,失敗返回-1。錯誤原因存在errno中
time_t time(time_t *t)
//傳入時間戳,返回tm結構體
struct tm* gmtime(const time_t *timep)
/***
struct tm
{
int tm_sec;//秒0~59
int tm_min;//分0~59
int tm_hour;//小時0~23
int tm_mday;//當前月份的日數 0~31
int tm_mon;//當前月份0~11
int tm_year;//從1900年到現在的年數
int tm_wday;//星期,星期一算起0~6
int tm_yday;//從1月1日起到今天的天數0~365
int tm_isdst;//夏時制時間
}
**/
//傳入tm結構體時間,返回字串時間
char * asctime(const struct tm *timeptr)
//傳入時間戳,返回tm結構的時間
struct tm * localtime(const time_t *timep)
#include<sys/time.h>
#include<unistd.h>
//
int gettimeofday(struct timeval *tv,struct timezone *tz)
/****
struct timeval{
long tv_sec;//秒
long tv_usec;//微秒
}
struct timezone{
int tz_minuteswest;//和GTM時間差了幾分鐘
int tz_dsttime;//日光節約時間的狀態
}
***/
環境控制函式
函式名 | 功能 |
---|---|
getenv | 取得環境變數的內容 |
pushenv/setenv | 改變或增加環境變數 |
unsetenv | 取消已經改變的環境變數 |
#include<stdlib.h>
//成功返回環境變數內容,失敗返回NULL
char *getenv(const char * name)
//成功返回0,出錯返回-1。 overwrite 0:忽略value 1:改變成引數value的內容
int setenv(const char *name, const char *value, int overwrite)
記憶體分配函式
函式名 | 功能 |
---|---|
calloc/malloc | 分配儲存空間 |
getpagesize | 獲取作業系統中記憶體分頁大小 |
mmap | 建立記憶體對映 |
munmap | 解除記憶體對映 |
free | 釋放分配的記憶體 |
#include<stdlib.h>
//分配記憶體size塊大小為nmemb的記憶體。失敗返回NULL。calloc會將記憶體初始化為0;
void * calloc(size_t nmemb, size_t size)
//分配size大小的記憶體,失敗返回NULL
void * malloc(size_t size)
#include<unistd.h>
size_t getpagesize(void)
//成功返回對映區的起始地址,失敗返回-1 (MAP_FAILED)
#include<unistd.h>
#include<sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize)
mmap函式引數: start:指向對應記憶體的起始地址。通常設為NULL length:代表檔案中多大的部分對應到記憶體 prot:對映區域的保護方式 PROT_EXEC:對映區域可被執行 PROT_READ:對映區域可被讀 PROT_WRITE:對映區域可被寫 PROT_NONE:對映區域不能存取 flags:對映區域的特性 PROT_EXEC:對映區域可被執行 PROT_READ:對映區域可被讀 PROT_WRITE:對映區域可被寫 PROT_NONE:對映區域不能存取 MAP_FIXED:start所指向的地址無法成功建立對映時,則放棄對映,不對地址做修正。 MAP_SHARED:對映區域的寫入資料複製迴文件,則允許其他對映該檔案的程序共享 MAP_PRIVATE:與shared相反,多個程序不共享。 fd:open()返回的檔案描述符 offsize:檔案對映偏移量,0代表從檔案頭開始 注意:呼叫mmap時必須指定MAP_SHARED或MAP_PRIVATE
資料結構中常用函式
函式名 | 功能 |
---|---|
bsearch | 二分法搜尋 |
lfind/lsearch | 線性搜尋 |
qsort | 快速排序排列陣列 |
#include<stdlib.h>
void qsort(void *base,size_t nmemb,size_t size, int (*compar)(const void *,const void *))
void *lfind(const void *key,const void *base,size_t *nmemb, size_t size,int (*compar)(const void *,const void *))
void *bsearch(const void *key,const void *base,size_t nmemb, size_t size,int (*compar)(const void *,const void *))
qsort()函式: base:陣列的起始地址 nmemb:陣列元素的數量 size:每個元素的大小 compar:函式指標。資料相同返回0,返回1時兩個資料交換,返回-1時兩個資料不交換。 lfind()/lsearch()/bsearch()函式: key:指向要查詢的資料的指標 base:陣列的起始地址 nmemb:陣列元素的數量 size:每個元素的大小 compar:函式指標。 lfind()和lsearch()不同點在於:當找不到資料時lfind()僅會返回NULL,而不會把資料加入到陣列尾部。lsearch()則會在找不到資料時將其加入陣列尾部
檔案系統API
chmod()函式
修改檔案許可權。成功返回0,失敗返回-1。錯誤存在errno中
#include<sys/types.h>
#include<sys/stat.h>
int chmod(const char* path,mode_t mode)
引數mode | 說明 |
---|---|
S_IRUSR | 所有者具有讀許可權 |
S_IWUSR | 所有者具有寫許可權 |
S_IXUSR | 所有者具有執行許可權 |
S_IRGRP | 組具有讀 |
S_IWGRP | … |
S_IXGRP | … |
S_IROTH | 其他使用者具有讀許可權 |
S_IWOTH | … |
S_IXOTH | … |
umask()函式
設定新檔案建立時的許可權掩碼
//返回原先的umask的值
mode_t umask(mode_t mask)
stat()函式
獲取檔案屬性。成功返回0,失敗返回-1,錯誤存入errno
#include<sys/stat.h>
#include<unistd.h>
int stat(const char* file_name,struct stat *buf)
struct stat{
dev_t st_dev; /* ID of device containing file -檔案所在裝置的ID*/
ino_t st_ino; /* inode number -inode節點號*/
mode_t st_mode; /* protection -保護模式?*/
nlink_t st_nlink; /* number of hard links -鏈向此檔案的連線數(硬連線)*/
uid_t st_uid; /* user ID of owner -user id*/
gid_t st_gid; /* group ID of owner - group id*/
dev_t st_rdev; /* device ID (if special file) -裝置號,針對裝置檔案*/
off_t st_size; /* total size, in bytes -檔案大小,位元組為單位*/
blksize_t st_blksize; /* blocksize for filesystem I/O -系統塊的大小*/
blkcnt_t st_blocks; /* number of blocks allocated -檔案所佔塊數*/
time_t st_atime; /* time of last access -最近存取時間*/
time_t st_mtime; /* time of last modification -最近修改時間*/
time_t st_ctime; /* time of last status change - */
}
scanf系列
#include<stdio.h>
int scanf(const char *format,...)
int fscanf(FILE *fp,const char *format,...)
int sscanf(const char *str,const char *format,...)
不帶快取的檔案IO
函式名 | 功能 |
---|---|
creat | 建立檔案 |
open | 開啟或建立檔案 |
close | 關閉檔案 |
read | 讀檔案 |
write | 寫檔案 |
lseek | 移動檔案的讀寫位置 |
flock | 鎖定檔案或解鎖檔案 |
fcntl | 操作檔案描述符 |
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//成功返回檔案描述符,失敗返回-1
int creat(const char *pathname,mode_t mode)
//成功返回最小的可用檔案描述符,失敗返回-1
int open(const char* pathname,int flags)
int open(const char* pathname,int flags, mode_t mode)
/***
flags:
O_RDONLY:只讀
O_WRONLY:只寫
O_RDWR:讀寫
O_APPEND:追加
O_TRUNG:設定檔案長度為0,且捨棄現存資料
O_CREAT:沒有則建立檔案,檔案許可權為mode
O_EXCL:與O_CREAT一起使用,若檔案已經存在,則建立檔案失敗
O_NONBLOCK:非阻塞式開啟檔案
***/
//成功返回0,失敗返回-1
int close(int fd)
#include<unistd.h>
//成功返回實際讀取或寫入的資料,失敗返回-1
ssize_t read(int fd,void *buf,size_t count)
ssize_t write(int fd,const void *buf,size_t count)
#include<sys/file.h>
//成功返回0,失敗返回-1,錯誤存入errno
int flock(int fd,int operation)
/***
operation:
LOCK_SH:建立共享鎖,多個程序可同時對一個檔案作共享鎖定
LOCK_EX:建立互斥鎖。
LOCK_UN:解除檔案鎖定
LOCK_NB:無法建立鎖定時,此操作可不被阻斷,馬上返回程序。與SH和EX與運算。
***/
#include<unistd.h>
#include<fcntl.h>
//成功返回0,失敗返回-1,錯誤存入errno
int fcntl(int fd,int cmd)
int fcntl(int fd,int cmd, long arg)
int fcntl(int fd,int cmd, struct flock *lock)
struct flock{
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
}
l_type:
F_RDLCK:讀鎖
F_WRLCK:寫鎖
F_UNLCK:解除鎖
l_whence:SEEK_SET,SEEK_CUR,SEEK_END
l_start:同l_whence
l_len:加鎖長度
l_pid:加鎖的程序id
帶快取的檔案IO
函式名 | 功能 |
---|---|
fopen | 開啟或建立檔案 |
fclose | 關閉檔案 |
fgetc | 從檔案讀取一個字元 |
fputc | 將一個字元寫入檔案 |
fgets | 從檔案讀取一字串 |
fputs | 將字串寫入檔案 |
fread | 從檔案流成塊讀取資料 |
fwrite | 將資料成塊寫入檔案 |
fseek | 移動檔案流讀寫位置 |
rewind | 重置檔案流的讀寫位置為檔案開頭 |
ftell | 獲取檔案流的讀取位置 |
#include<stdio.h>
//成功返回指標,失敗返回NULL
FILE * fopen(const char * path,const char* mode)
/***
mode:
r:只讀
r+:開啟可讀寫檔案
w:只寫。檔案存在則清空檔案,不存在則建立檔案
w+:開啟可讀寫檔案
a:追加方式開啟。不存在則建立檔案,存在則在檔案尾部追加內容
a+:開啟可讀寫檔案
上面的選項中加入b,則表示用二進位制方式開啟檔案,比如ab+
***/
//成功返回0,失敗返回EOF
int fclose(FILE *stream)
//成功返回讀取的字元,失敗返回EOF
int fgetc(FILE * fp)
//成功返回寫入的字元,失敗返回EOF
int fputc(int ch,FILE *fp)
//成功返回s指標,失敗返回EOF
char * fgets(char *s,int size,FILE *fp)
//成功返回寫入的字元個數,失敗返回EOF
int fputs(const char *str, FILE * fp)
//成功返回實際的讀寫nmemb數,失敗返回EOF
size_t fwrite(const void * ptr,size_t size, size_t nmemb,FILE *fp)
size_t fread(void * ptr, size_t size,size_t nmemb,FILE * fp)
//成功返回0,失敗返回-1
int fseek(FILE *fp, long offset, int whence)
//成功返回檔案當前讀寫位置,失敗返回-1
long ftell(FILE *fp)
//
void rewind(FILE *fp)
特殊檔案操作
目錄檔案
#include<dirent.h>
struct __dirstream
{
void *__fd; /* `struct hurd_fd' pointer for descriptor. */
char *__data; /* Directory block. */
int __entry_data; /* Entry number `__data' corresponds to. */
char *__ptr; /* Current pointer into the block. */
int __entry_ptr; /* Entry number `__ptr' corresponds to. */
size_t __allocation; /* Space allocated for the block. */
size_t __size; /* Total valid data in the block. */
__libc_lock_define (, __lock) /* Mutex lock for this structure. */
};
typedef struct __dirstream DIR;
struct dirent
{
long d_ino; /* inode number 索引節點號 */
off_t d_off; /* offset to this dirent 在目錄檔案中的偏移 */
unsigned short d_reclen; /* length of this d_name 檔名長 */
unsigned char d_type; /* the type of d_name 檔案型別 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 檔名,最長255字元 */
}
#include<sys/types.h>
#include<dirent.h>
//成功返回DIR指標,失敗返回NULL
DIR *opendir(const char* name)
//成功返回0,失敗返回-1,錯誤存入errno
int closedir(DIR *dir)
#include<sys/types.h>
#include<dirent.h>
#include<fcntl.h>
//成功返回下一個目錄進入點,失敗返回NULL
struct dirent * readdir(DIR *dir)
//返回目錄流當前位置
long int telldir(DIR * dirp)
//loc可以是telldir的返回值。該函式設定目錄流指標的位置
void seekdir(DIR *dirp,long int loc)
#include<sys/types.h>
#include<sys/stat.h>
//建立目錄,同mkdir命令
int mkdir(const char *path, mode_t mode)
#include<unistd.h>
//刪除目錄,但是隻有在目錄為空時才行。同rmdir命令
int rmdir(const char *path)
//切換當前目錄,同cd命令
int chdir(const char * path)
//獲取當前目錄,同pwd命令
char *getcwd(char *buf,size_t size)
連結檔案
#include<unistd.h>
//建立軟連結。成功返回0,失敗返回-1,錯誤存入errno
int symlink(const char * oldpath,const char * newpath)
//建立硬連結。成功返回0,失敗返回-1,錯誤存入errno
int link(const char * oldpath,const char * newpath)
//刪除檔案。成功返回0,失敗返回-1;
int unlink(const char *path)
編寫守護程序
守護程序最重要的特性就是後臺執行,其次是與執行的環境隔開,環境包括檔案描述符,控制終端,會話工作目錄等,這些環境通常是從執行他的父程序(特別是shell)中繼承來的。
編寫守護程序的要點:
- 建立子程序,終止父程序。(使之成為殭屍程序)
- 在子程序中建立新會話。這個步驟是建立守護程序最重要的一步。需要使用系統函式setsid()。這個函式有三個作用:1,讓程序擺脫原會話的控制;2,讓程序擺脫原程序組的控制;3,讓程序擺脫原控制終端的控制。
- 改變工作目錄。可以呼叫chdir()函式將當前工作目錄換為/或/tmp或其他路徑
- 重設檔案建立掩碼。
- 關閉檔案描述符。從父程序繼承的已經開啟的檔案可能永遠不會被守護程序使用,如果不關閉會導致資源浪費。可能導致所在檔案系統無法解除安裝。
#include<sys/types.h>
#include<unistd.h>
//設定新的組程序號,成功返回程序組號,失敗返回-1,錯誤存入errno
pid_t setsid(void)
示例程式:
#include<unistd.h>
#include<stdio.h>
#include<time.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
void init_deamon(void)
{
pid_t child1,child2;
int i;
child1 = fork();//建立子程序,終止父程序
if(child1 > 0){
exit(0);
}else if(child1 < 0){
perror("建立程序失敗!\n");
exit(1);
}
setsid();//子程序中建立新會話
chdir("/tmp");//改變工作目錄
umask(0);//重設umask
for(i = 0; i < NOFILE;i++){
close(i);//關閉檔案描述符
}
return;
}
int main()
{
FILE *fp;
time_t t;
init_deamon();
while(1){
sleep(10);
if((fp = fopen("deamon.log","a+")) != NULL){
t = time(0);
fprintf(fp,"守護程序還在執行,時間是:%s\n",asctime(localtime(&t)));
fclose(fp);
}
}
return 0;
}
日誌相關函式
#include<syslog.h>
//準備做資訊記錄
void openlog(char * ident, int option, int facility)
/***
option:
LOG_CONS:如果無法將資訊送到syslogd則直接輸出到控制檯
LOG_PID:將資訊字串加上產生資訊的程序號PID
LOG_PERROR:同時輸出到stderr
LOG_NODELAY:立即開啟連線
LOG_NOWAIT:不要等待子程序
LOG_ODELAY:延遲連線的開啟,直到呼叫syslog()
facility:代表資訊種類
LOG_CRON:由cron或at程式產生的資訊
LOG_DEAMON:由系統deamon產生的資訊
***/
//將資訊記錄到系統日誌檔案
void syslog(int priority, char * format, ...)
/***
priority:指定資訊種類或等級
LOG_INFO:提示相關資訊
LOG_DEBUG:出錯相關資訊
***/
注意以上兩個函式必須具有root許可權才行
程序間通訊
訊號
使用kill -l可以列出系統支援的所有訊號
1~31以SIG開頭(非實時訊號)、34~49以SIGRTMIN開頭是繼承Unix系統的訊號稱為不可靠訊號(非實時訊號)、50~64以SIGRTMAX開頭是對前面不可靠訊號的更改和擴充,稱為可靠訊號(實時訊號)
可靠訊號:支援排隊,使用者傳送一次就註冊一次。
不可靠訊號:不支援排隊,使用者傳送一次,先判斷有沒有相同的訊號已經註冊,如果有則不再註冊。
常見訊號及其預設操作:
訊號名 | 含義 | 預設操作 |
---|---|---|
SIGHUP | 該訊號在使用者終端連線(正常或非正常)結束時發出 | 終止 |
SIGINT | 使用者在按下中斷鍵<ctrl+c>時,系統會向該終端相關程序傳送此訊號 | 終止 |
SIGQUIT | 該訊號在使用者按下<ctrl+>退出鍵時,系統會發送此訊號,造成程序非正常終止 | 終止 |
SIGILL | 該訊號在一個程序企圖執行一條非法指令時發出(可執行檔案本身錯誤,或者企圖執行資料段堆疊溢位時) | 終止 |
SIGFPE | 該訊號在發生致命算術運算錯誤時發出 | 終止 |
SIGKILL | 用來立即結束程式的執行,且不能被阻塞,處理或忽略 | 終止 |
SIGALRM | 該訊號在定時器計時完成時發出,定時器可用程序呼叫alarm()函式來設定 | 終止 |
SIGSTOP | 用於暫停程序,且不能能被阻塞,處理或忽略 | 暫停程序 |
SIGTSTP | 使用者按下<ctrl+z>掛起鍵時系統傳送此訊號,程序掛起 | 停止程序 |
SIGCHLD | 該訊號在子程序結束時向父程序發出。當子程序運行了exit()函式,就會向父程序傳送此訊號,如果父程序呼叫了wait()函式,則父程序被喚醒。如果父程序沒有呼叫wait()函式,則忽略此訊號,子程序將變成殭屍程序。 | 忽略 |
訊號操作相關函式
函式名 | 功能 |
---|---|
kill | 傳送SIGKILL訊號給程序或程序組 |
raise | 傳送訊號給程序或自身 |
alarm | 定時器時間到,向程序傳送SIGALRM訊號 |
pause | 沒有捕捉到訊號前一直將程序掛起 |
signal | 捕捉訊號SIGINT,SIG_IGN,SIG_DFL,SIGQUIT時執行訊號處理函式 |
sigemptyset | 初始化訊號集合為空 |
sigfillset | 初始化訊號集合為所有訊號集合 |
sigaddset | 將指定訊號新增到指定集合 |
sigdelset | 從集合刪除指定訊號 |
sigismember | 查詢指定訊號是否在訊號集合中 |
sigprocmask | 判斷監測或更改訊號遮蔽字 |
#include<sys/types.h>
#include<signal.h>
//傳送訊號給指定程序。成功返回0,失敗返回-1
int kill(pid_t pid, int sig)
/***
pid:
pid>0:將訊號傳遞給pid的程序
pid=0:將訊號傳遞給當前程序相同程序組的所有程序
pid=-1:將訊號廣播給系統內所有程序
pid<-1:將訊號傳遞給程序組識別碼為pid絕對值的所有程序
sig:Linux系統訊號
***/
//傳送訊號給當前程序。成功返回0,失敗返回-1
int raise(int sig)
//設定訊號處理函式
void (*signal(int signum,void(*handler)(int))) (int)
#include<signal.h>
//成功返回0,失敗返回-1
int sigemptyset(sigset_t *set)
//成功返回0,失敗返回-1
int sigaddset(sigset_t * set, int signum)
//查詢或設定訊號掩碼。成功返回0,失敗返回-1
int sigprocmask(int how,const sigset_t * set, sigset_t * oldset)
/***
how:
SIG_BLOCK:新的掩碼有當前訊號掩碼和引數set指定的訊號掩碼作聯集
SIG_UNBLOCK:將目前訊號掩碼刪除掉引數set指定的訊號掩碼
SIG_SETMASK:將目前掩碼設定成set指定的掩碼
***/
管道
無名管道
通過pipe()函式實現無名管道建立。無名管道通過int pipe_fd[2];來實現管道的兩端,pipe_fd[0]是讀端,pipe_fd[1]是寫端。
用在父子程序通訊:
- 父程序呼叫pipe()開闢管道
- 父程序呼叫fork()建立子程序,那麼子程序也繼承得到了相同的管道
- 父程序關閉管道讀端,子程序關閉管道寫端,從而就能將資料在父程序寫入,在子程序讀取。如果想實現雙向,那就再使用一個管道。
#include<unistd.h>
//建立無名管道,成功返回0,失敗返回-1
int pipe(int filedes[2])
示例程式:
......
#include<unistd.h>
int main()
{
int fds[2];
......
if(pipe(fds) < 0){
perror("建立管道失敗\n");
exit(0);
}
......
chld = fork();
if(chld == 0){
close(fds[1]);
read(fds[0],buf,100);
......
close(fds[0]);
......
}
if(chld > 0){
close(fds[0]);
write(fds[1],buf,strlen(buf));
......
close(fds[1]);
waitpid(chld,NULL,0);
......
}
}
命名管道(FIFO)
該管道有名字,所以就能在任何有許可權的程序間使用。
#include<sys/types.h>
#include<sys/stat.h>
//建立命名管道。成功返回0,失敗返回-1,錯誤存入errno
int mkfifo(const char* pathname, mode_t mode)
/***
pathname:指定管道檔案位置,該檔案必須不存在,否則建立失敗。
mode:為建立的管道檔案許可權。跟umask會影響最終的值
***/
#include<stdio.h>
//建立管道IO。成功返回檔案流指標,失敗返回NULL,錯誤存入errno
FILE * popen(const char * command,const char * type)
/***
command:linux命令,例如ls -l等
type:"r","w"分別表示讀,寫。
***/
注意:編寫具有SUID/SGID的程式時,避免使用popen(),因為popen()會繼承環境變數,可能會造成安全問題
示例程式:
......
#include<sys/types.h>
#include<sys/stat.h>
int main()
{
int rfd,wfd;
......
mkfifo("fifo1",S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
wfd = open("fifo1",O_WRONLY);
......
write(wfd,buf,strlen(buf));
......
close(wfd);
......
}
......
#include<stdio.h>
int main()
{
FILE *fp;
......
fp = popen("ls -l","r");
......
fread(buf,sizeof(char),5000,fp);
......
pclose(fp);
......
}
訊息佇列
函式名 | 功能 |
---|---|
ftok | 由檔案路徑和工程ID生成標準key |
msgget | 建立或開啟訊息佇列 |
msgsnd | 新增訊息 |
msgrcv | 讀取訊息 |
msgctl | 控制訊息佇列 |
#include<sys/types.h>
#include<sys/ipc.h>
//成功返回key值,失敗返回-1,錯誤存入errno
key_t ftok(char * pathname,char proj)
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys.msg.h>
//成功返回訊息佇列識別號,失敗返回-1,錯誤存入errno
int msgget(key_t key,int msgflg)
/***
key:ftok函式生成的key,如果傳入IPC_PRIVATE則建立新的訊息佇列
msgflg:決定訊息佇列的存取許可權
***/
//成功返回0,失敗返回-1.錯誤存入errno
int msgsnd(int msgid,struct msgbuf * msgp ,int msgsz,int msgflg)
/***
msgid:訊息佇列識別號
msgp:使用者自定義的結構體指標,形態如下
struct msgbuf{
long mtype;//訊息型別,必須大於0
char mtext[1];//訊息文字
}
msgsz:訊息的大小
msgflg:用來指明核心程式在訊息佇列沒有訊息的情況下采取的行動
***/
//成功返回實際讀取的訊息資料長度,失敗返回-1,錯誤存入errno
int msgrcv(int msgid,struct msgbuf * msgp,int msgsz,long msgtyp,int msgflg)
/***
msgtyp:用來指定所要讀取的訊息型別。
=0:返回佇列的第一項訊息
>0:返回佇列中第一項msgtyp和mtype相同的訊息
<0:返回佇列第一項mtype小於或等於msgtyp絕對值的訊息
***/
//成功返回0,失敗返回-1,錯誤存入errno
int msgctl(int msgid,int cmd,struct msqid_ds *buf)
/***
cmd:
IPC_STAT:讀取訊息佇列的資料結構msqid_ds,並將其儲存在buf指定的地址中。
IPC_SET:設定訊息佇列的資料結構msqid_ds中的ipc_perm元素的值。這個值取自buf引數。
IPC_RMID:從系統核心中移走訊息佇列。
***/
示例程式:
......
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
struct msgbuf{
long mtype;//訊息型別,必須大於0
char mtext[512];//訊息文字
}
int main()
{
......
key_t key;
int qid;
struct msgbuf msg;
key = ftok(".","a");
......
qid = msgget(key,IPC_CREAT | 0666);
......
msg.mtype = getpid();
strcpy(msg.mtext,"hhhhhhhh");
......
msgsnd(qid,&msg,strlen(msg.mtext),0);
......
msgrcv(qid,&msg,512,0,0);
......
msgctl(qid,IPC_RMID,NULL)
......
}
共享記憶體
函式名 | 功能 |
---|---|
mmap | 建立共享記憶體對映 |
munmap | 解除共享記憶體對映 |
shmget | 獲取共享記憶體區域ID |
shmat | 建立對映共享記憶體 |
shmdt | 解除共享記憶體對映 |
#include<unistd.h>
#include<sys/mman.h>
//建立記憶體對映.成功返回對映去的記憶體起始地址,失敗返回-1,錯誤存入errno
void * mmap(void * start, size_t length, int prot, int flags, int fd, off_t offsize)
/***
prot:對映區域保護方式
PROT_EXEC:對映區域可被執行
PROT_READ:對映區域可被讀
PROT_WRITE:對映區域可被寫
PROT_NONE:對映區域不能存取
flags:特性
PROT_EXEC:對映區域可被執行
PROT_READ:對映區域可被讀
PROT_WRITE:對映區域可被寫
PROT_NONE:對映區域不能存取
MAP_FIXED:start所指向的地址無法成功建立對映時,則放棄對映,不對地址做修正。
MAP_SHARED:對映區域的寫入資料複製迴文件,則允許其他對映該檔案的程序共享
MAP_PRIVATE:與shared相反,多個程序不共享。
***/
//成功返回0,失敗返回-1,錯誤存入errno
int munmap(void *start, size_t length)
/****
length:欲取消記憶體的大小
***/
示例程式:
......
#include<unistd.h>
#include<sys/mman.h>
struct people{
char name[4];
int age;
};
int main()
{
pid_t chld;
people * p_map;
......
p_map = (people *)mmap(NULL,sizeof(people)*10,PROT_READ | PROT_WRITE|MAP_SHARED | MAP_ANONYMOUS,-1,0);
......
chld = fork();
......
if(chld == 0){
for(int i = 0;i < 5;i++){
printf("第%d個人,姓名:%s,年齡:%d\n",(p_map+i)->name,(p_map+i)->age);
}
munmap(p_map,sizeof(people)*10);
......
}
if(chld > 0){
for(int i = 0;i < 5;i++){
memcpy((p_map+i)->name,'a'+i,2);
(p_map+i)->age = i;
}
......
munmap(p_map,sizeof(people)*10);
}
}
UNIX Systeem V共享記憶體
#include<sys/ipc.h>
#include<sys/shm.h>
//成功返回共享記憶體識別號,失敗返回-1,錯誤存入errno
int shmget(key_t key, int size, int shmflg)
/***
key:為IPC_PRIVATE則建立新的共享記憶體,大小有四則決定
***/
//對映共享記憶體,成功返回記憶體的起始地址,失敗返回-1,錯誤存入errno
void * shmat(int shmid, const void * shmaddr, int shmflg)
/***
shmid:共享記憶體識別號
shmaddr:
=0:核心自動選擇地址
!=0且shmflg沒有指定SHM_RND旗標,則以引數shmaddr為連線地址。
!=0且指定SHM_RND旗標:引數shmaddr會自動調整為SHMLBA的整數倍
***/
//成功返回0,失敗返回-1,錯誤存入errno
int shmdt(const void * shmaddr)mmap
mmap和unix system v兩類共享記憶體的區別在於mmap用的普通檔案實現共享記憶體,而unix system v則用的特殊檔案系統shm中的檔案實現共享記憶體。