1. 程式人生 > >c(4)檔案鎖+程序

c(4)檔案鎖+程序

1)檔案鎖

為了避免在讀寫同一個檔案的同一個區域時發生衝突,程序之間應該遵循以下規則:如果一個程序正在寫,那麼其他程序既不能寫也不能讀;如果一個程序正在讀,那麼其他程序不能寫但是可以讀。

2)
檔案元資料(檔案屬性資訊)

//node.c

輸出:

-rrSr-rr--

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//得到檔案型別、許可權等資訊
const char *mtos(mode_t m){
	static char s[11];
	if(S_ISDIR(m))//是否目錄
	    strcpy(s,"d");
	else if(S_ISSOCK(m))//是否本地套接字
	    strcpy(s,"s");
	else if(S_ISCHR(m))//是否字元裝置
	    strcpy(s,"c");
	else if(S_ISBLK(m))//是否塊裝置
	    strcpy(s,"b");
	else if(S_ISLNK(m))//是否符號連結
	    strcpy(s,"l");
	else if(S_ISFIFO(m))//是否有名管道
	    strcpy(s,"p");
	else
	    strcpy(s,"-");//是否普通檔案
	//使用者讀、寫、執行
	strcat(s,m&S_IRUSR?"r":"-");
	strcat(s,m&S_IWUSR?"r":"-");
	strcat(s,m&S_IXUSR?"r":"-");
	//組成員讀、寫、執行
	strcat(s,m&S_IRGRP?"r":"-");
	strcat(s,m&S_IWGRP?"r":"-");
	strcat(s,m&S_IXGRP?"r":"-");
	//其他人讀、寫、執行
	strcat(s,m&S_IROTH?"r":"-");
	strcat(s,m&S_IWOTH?"r":"-");
	strcat(s,m&S_IXOTH?"r":"-");
	if(m&S_ISUID)//使用者ID
	    s[3]=(s[3]=='x'?'s':'S');
	if(m&S_ISGID)//組ID
	    s[3]=(s[3]=='x'?'s':'S');
	if(m&S_ISVTX)//粘滯位
	    s[3]=(s[3]=='x'?'s':'S');
	return s;
}
int main(){
	int fd=open("data.txt",O_RDWR,0666);
	if(fd==-1){
		perror("open");
		exit(EXIT_FAILURE);
	}
	struct stat statdata;
	fstat(fd,&statdata);//用函式fstat提取檔案fd的元資料
	printf("%s\n",mtos(statdata.st_mode));
	if(close(fd)==-1){
		perror("close");
		exit(EXIT_FAILURE);
	}
}

硬連結:[link函式]

本質就是目錄檔案裡一個檔名和i節點號的對應條目,通過該節點,就可以根據一個檔案的檔名迅速地找到與之相對應的節點號,進而訪問該檔案的資料。
軟連結(符號連結):[symlink函式]
本質就是一個儲存著另一個檔案或目錄的路徑的檔案。所有針對符號連結檔案的訪問,最後都會被定向到該符號連結所引用的目標檔案或目錄。

3)

建立子程序

//02pid.c

輸出:

執行fork前帶有換行符
執行fork前沒有換行符 這是子程序,pid=3472,父程序的pid=3471
,pid=3472,glob=7,var=89
[停頓10秒]執行fork前沒有換行符 這是父程序,pid=3471
pid=3471,glob=6,var=88

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int glob=6;
int main(){
	int var=88;
	pid_t pid;
//呼叫fork函式前的程式碼只有父程序執行,fork函式成功返回後
//的程式碼子程序和父程序都會執行,受邏輯控制進入不同分支。
//printf函式帶\n和不帶\n是有區別的,因為不帶\n時,並不是馬上
//更新顯示緩衝區,所以造成好像子和父程序都執行了此語句的假象
	printf("執行fork前帶有換行符\n");
	printf("執行fork前沒有換行符 ");
	if((pid=fork())<0){
		perror("fork");
	}//fork函式建立子程序,呼叫一次,在子程序和父程序中各
	//返回一次,在子程序中返回所建立子程序的PID,而在子程序
	//中返回0
	else if(pid==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n,",getppid());
		glob++;
		var++;
	}
	else{
		sleep(10);
		printf("這是父程序,pid=%d\n",getpid());
	}
	printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var);
	return 0;
}

建立輕量級子程序
vfork函式建立的子程序不復制父程序的實體記憶體,也不擁有自己獨立的記憶體對映,而是與父程序共享全部地址空間。vfork函式會在建立子程序的同時掛起其父程序,直到子程序終止,或通過exec函式啟動了另一個可執行程式。

//05vfork.c

輸出:

父程序開始執行。
子程序開始執行。
excel: No such file or directory
[停頓1秒]父程序執行結束。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
	printf("父程序開始執行。\n");
	pid_t pid=vfork();
	if(pid==-1){
		perror("vfock");
		exit(EXIT_FAILURE);
	}
	if(pid==0){
		printf("子程序開始執行。\n");
		if(execl("ls","ls","-l",NULL)==-1){
			perror("excel");
			_exit(EXIT_FAILURE);
		}
	}
	sleep(1);
	printf("父程序執行結束。\n");
	return 0;
}



父子程序共享檔案表
fork函式成功返回後,系統核心維護的檔案描述符也被複制到子程序的程序表項中,檔案表項並不複製,所以子程序和父程序寫入統一檔案

//04fork.c

輸出:

111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024
111111111->0,buf[0]=0,writed=1024

......

data.txt內容:

111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111    111111111111111111111111111111111111111111111111111111111111111111111

......

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#define BUFSIZE 1024*1024
bool lock(int fd){
	struct flock lock;
	lock.l_type=F_WRLCK;
	lock.l_whence=SEEK_SET;
	lock.l_start=0;
	lock.l_len=0;
	lock.l_pid=-1;
	if(fcntl(fd,F_SETLK,&lock)==-1){
		if(errno!=EAGAIN){
			perror("fcntl");
			exit(EXIT_FAILURE);
		}
		return false;
	}
	return true;
}
void unlock(int fd){
	struct flock lock;
	lock.l_type=F_UNLCK;
	lock.l_whence=SEEK_SET;
	lock.l_start=0;
	lock.l_len=0;
	lock.l_pid=-1;
	if(fcntl(fd,F_SETLKW,&lock)==-1){
		perror("fcntl");
		exit(EXIT_FAILURE);
	}
}
//函式writedata向檔案fd寫入資料
void writedata(int fd,char *buf,char c){
	while(!lock(fd));//設定寫鎖,防止子程序和父程序同時寫入造成資料混亂
	for(int i=0;i<BUFSIZE-1;i++)
	    buf[i]=c;
	for(int i=0;i<1024;i++){
	    	int writed;
		if((writed=write(fd,buf+i,1024))==-1){
			perror("write");
			exit(EXIT_FAILURE);
		}
		printf("111111111->%c,buf[0]=%c,writed=%d\n",c,*(buf+i),writed);
	}
	unlock(fd);
}
int main(){
	int fd=open("data.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
	if(fd==-1){
		perror("open");
		exit(EXIT_FAILURE);
	}
	pid_t pid;
	if((pid=fork())<0){
		perror("fork");
		return 1;
	}
	if(pid==0){//子程序向檔案中寫入0
		char buf[BUFSIZE]={};
		writedata(fd,buf,'0');
	}
	else{//父程序向檔案中寫入1
		char buf[BUFSIZE]={};
		writedata(fd,buf,'1');
	}
	if(close(fd)==-1){
		perror("close");
		exit(EXIT_FAILURE);
	}
	return 0;
}


4)
孤兒與殭屍
孤兒:
子程序被暫停了10秒鐘,所以當父程序退出時,子程序仍然未退出。這樣子程序即成為孤兒程序。當暫停的10秒鐘結束時,子程序的父程序變成了1,即init程序,又被稱為孤兒院程序。

//01.c

輸出:

[email protected]:~/case8$ ./a.out
這是父程序,pid=3686[等待10秒]
[email protected]:~/case8$ 這是子程序,pid=3687父程序的pid=1221[程序未退出]

^C

/孤兒程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
	pid_t pid;
	if((pid=fork())<0){
		perror("fork");
	}
	else if(pid==0){
		sleep(10);
		printf("這是子程序,pid=%d",getpid());
		printf("父程序的pid=%d\n",getppid());
	}
	else{
		printf("這是父程序,pid=%d\n",getpid());
	}
	return 0;
}
殭屍:
指定父程序休眠的秒數,在這10秒內,子程序已經退出,而父程序休眠,不可能對它進行收集,這樣,我們就能獲得10秒的殭屍狀態。
//02.c

輸出:

這是子程序,pid=3722父程序的pid=3721[等待10秒]

這是父程序,pid=3721

//殭屍程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
	pid_t pid;
	if((pid=fork())<0){
		perror("fork");
	}
	else if(pid==0){
		printf("這是子程序,pid=%d",getpid());
		printf("父程序的pid=%d\n",getppid());
	}
	else{
	    	sleep(10);
		printf("這是父程序,pid=%d\n",getpid());
	}
	return 0;
}

5)
程序的正常終止
<stdlib.h>
void exit(int status);
int atexit(void (*function)(void));
int on_exit(void (*function)(int , void *), void *arg);

void exit(int status);
exit函式呼叫,立即令呼叫程序終止

int atexit(void (*function)(void));

函式atxit為註冊退出處理函式,該函式有一個引數是退出處理函式指標,所指向的函式必須既無返回值亦無引數,在程序終止前被呼叫,為程序料理臨終事宜。atexit函式本身並不呼叫退出處理函式指標,只是將doexit引數所表示的退出處理函式地址,儲存(註冊)在系統核心的某個地方(程序表項)。待到exit函式被呼叫或在main函式裡執行return語句時,再由系統核心根據這些退出處理函式的地址來呼叫它們,此過程亦稱回撥。

//06atexit.c
輸出:
主函式退出了。

註冊的退出處理函式被呼叫了。

#include <stdio.h>
#include <stdlib.h>
void doexit(){
	printf("註冊的退出處理函式被呼叫了。\n");
}
int main(){
	atexit(doexit);
	printf("主函式退出了。\n");
	return 0;
}

int on_exit(void (*function)(int , void *), void *arg);

使用函式on_exit註冊退出處理函式,該函式有兩個引數,第一個引數為退出處理函式指標,所指向的函式必須無返回值但有兩個引數。其中一個引數來自傳遞給exit函式的statues引數或在main函式裡執行return語句的返回值,而第二個引數則來自傳遞給on_exit函式的arg引數。該函式在程序終止前被呼叫,為程序料理臨終事宜。第二個引數為泛型指標,將作為第二個引數傳遞給function所指向的退出處理函式。

//06on_exit.c
輸出:
主函式退出了。

註冊的退出處理函式被呼叫了。

#include <stdio.h>
#include <stdlib.h>
//定義退出處理函式,用作退出處理函式,處理函式退出前必做的一些工作
void doexit(int status,void *arg){
	printf("%s",(char *)arg);
}
int main(){
	on_exit(doexit,"註冊的退出處理函式被呼叫了。\n");
	printf("主函式退出了。\n");
	return 0;
}

[_exit、_Exit和exit的區別:

_exit、_Exit函式和exit函式一樣也是正常終止呼叫,但它們影響的完全是呼叫程序自己的資源,與其父程序沒有任何關係。在用vfork函式建立的子程序存在太多與其父程序共享的資源。如果在子程序裡呼叫了exit函式或在子程序的main函式裡執行了return語句(這二者在本質上是等價的),不僅銷燬了子程序的資源,同時也銷燬了父程序的資源,而父程序恰恰要在子程序終止以後從掛起中恢復執行,其後果可想而知。
]


6)
<sys/types.h>
<sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);

回收任意或所有子程序
pid_t wait(int *wstatus);
父程序在建立若干子程序以後呼叫wait函式,此時若所有子程序都在執行,則wait阻塞,直至有子程序終止;若有一個子程序已終止,則wait返回該子程序的PID並通過status引數(若非NULL)輸出其終止狀態;若沒有需要等待的子程序,則wait返回-1,置errno為ECHILD。
//07.c
輸出:
這是父程序,pid=5926
這是子程序,pid=5928,父程序的pid=5926
這是子程序,pid=5927,父程序的pid=5926

5927子程序終止5928子程序終止子程序都死光了

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
int main(){
	pid_t pid1;
	if((pid1=fork())<0)
	    perror("fork");
	if(pid1==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n",getppid());
		_exit(0);
	}
	pid_t pid2;
	if((pid2=fork())<0)
	    perror("fork");
	if(pid2==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n",getppid());
		_exit(0);
	}
	printf("這是父程序,pid=%d\n",getpid());
	//等待並回收所有子程序,忽略其終止狀態。
	while(1){
		pid_t pid=wait(NULL);
		if(pid==-1){
			if(errno!=ECHILD){
				perror("wait");
				exit(EXIT_FAILURE);
			}
			printf("子程序都死光了\n");
			break;
		}
		printf("%d子程序終止",pid);
	}
	return 0;
}

非阻塞模式回收所有子程序

pid_t waitpid(pid_t pid, int *wstatus, int options);
wstatus為輸出子程序的終止狀態,可置NULL
options=0,阻塞模式
options=WNOHANG,非阻塞模式
使用函式waitpid以非阻塞方式回收任意子程序
//09.c
輸出:
這是父程序,pid=6420
在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處�這是子程序,pid=6422,父程序的pid=6420
這是子程序,pid=6421,父程序的pid=6420
��在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理在這裡進行空閒處理6421子程序終止
6422子程序終止

子程序都死光了

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
int main(){
	pid_t pid1;
	if((pid1=fork())<0)
	    perror("fork");
	if(pid1==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n",getppid());
		_exit(0);
	}
	pid_t pid2;
	if((pid2=fork())<0)
	    perror("fork");
	if(pid2==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n",getppid());
		_exit(0);
	}
	printf("這是父程序,pid=%d\n",getpid());
//非阻塞模式等待並回收所有子程序,等待的同時做空閒處理。
	while(1){
		pid_t pid=waitpid(-1,NULL,WNOHANG);
		if(pid==-1){
//errno==ECHILD表示已沒有可回收的子程序了
			if(errno!=ECHILD){
				perror("wait");
				exit(EXIT_FAILURE);
			}
			printf("子程序都死光了\n");
			break;
		}
		if(pid)
//成功回收該子程序
		    printf("%d子程序終止\n",pid);
		else 
//所等子程序仍在執行,此時父程序出現空閒時間,可在這裡進行空閒處理
		    printf("在這裡進行空閒處理");
	}
	return 0;
}

回收特定子程序

無論一個程序是正常終止還是異常終止,都會通過系統核心向其父程序傳送SIGCHILD(17)訊號,父程序可以忽略該訊號,也可以提供一個針對該訊號的訊號處理函式,在訊號處理函式中以非同步的方式回收該子程序。這樣不僅流程簡單,而且殭屍的存活時間短,回收效率高。
//08.c
輸出:
這是父程序,pid=5979
這是子程序,pid=5980,父程序的pid=5979

5980子程序終止5979父程序終止

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
int main(){
	pid_t pid;
	if((pid=fork())<0)
	    perror("fork");
	if(pid==0){
		printf("這是子程序,pid=%d,",getpid());
		printf("父程序的pid=%d\n",getppid());
		_exit(0);
	}
	else
		printf("這是父程序,pid=%d\n",getpid());
	//等待並回收所有子程序,忽略其終止狀態。
		pid=waitpid(pid,NULL,0);
		if(pid==-1){
			if(errno!=ECHILD){
				perror("wait");
				exit(EXIT_FAILURE);
			}
		}
		else
			printf("%d子程序終止",pid);
		printf("%d父程序終止\n",getpid());
	return 0;
}

7)建立新程序的exec函式族
與fork或vfork函式不同,exec函式不是建立呼叫程序的子程序,而是建立一個新的程序取代呼叫程序自身。新程序會用自己的全部地址空間,覆蓋呼叫程序的地址空間,但程序的PID保持不變。
<unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...
                       /* (char  *) NULL */);
int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);
int execle(const char *path, const char *arg, ...
                       /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
                       char *const envp[]);
int execve(const char *filename, char *const argv[],

                  char *const envp[]);

//10execl.c

輸出:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
	if(execl("/bin/pwd","pwd",NULL)==-1){
		perror("execl");
		exit(EXIT_FAILURE);
	}
	printf("本函式執行完畢");
	return 0;
}

//10execle.c

輸出:

/home/y/case8

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
	char *envp[]={"HOME=/home/y",NULL};
	if(execle("/bin/pwd","pwd",NULL,envp)==-1){
		perror("execl");
		exit(EXIT_FAILURE);
	}
	printf("本函式執行完畢");
	return 0;
}

//10execlp.c

輸出:

/home/y/case8

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
	if(execlp("pwd","pwd",NULL)==-1){
		perror("execl");
		exit(EXIT_FAILURE);
	}
	printf("本函式執行完畢");
	return 0;
}

//10vexec.c

輸出:

本函式執行完畢
/home/y/case8
3086子程序終止

3085父程序終止

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
	pid_t pid=vfork();
	if(pid==-1){
		perror("vfork");
		exit(EXIT_FAILURE);
	}
	if(pid==0){
		if(execl("/bin/pwd","pwd",NULL)==-1){
			perror("execl");
			exit(EXIT_FAILURE);
		}
		_exit(0);
	}
	else
	    printf("本函式執行完畢\n");
	pid=wait(NULL);
	    if(pid==-1 && errno!=ECHILD){
	    	perror("wait");
		exit(EXIT_FAILURE);
	    }
	printf("%d子程序終止\n",pid);
	printf("%d父程序終止\n",getpid());
	return 0;
}

使用system函式可以執行shell命令

//11system.c

輸出:

Shell不可用

#include <stdio.h>
#include <stdlib.h>
int main(){
	int status;
	if(status=system(NULL)==-1){
		perror("system");
		exit(EXIT_FAILURE);
	}
	if(!status)
	    printf("Shell不可用\n");
	else{
		if((status=system("ls -l"))==-1){
			perror("system");
			exit(EXIT_FAILURE);
		}
		printf("%d\n",WEXITSTATUS(status));
	}
	return 0;
}


相關推薦

c(4)檔案+程序

1)檔案鎖為了避免在讀寫同一個檔案的同一個區域時發生衝突,程序之間應該遵循以下規則:如果一個程序正在寫,那麼其他程序既不能寫也不能讀;如果一個程序正在讀,那麼其他程序不能寫但是可以讀。2)檔案元資料(檔案屬性資訊)//node.c輸出:-rrSr-rr--#include &

c++建立四個程序輪流列印BACDBACD(利用

#include<stdio.h> #include<pthread.h> #include<semaphore.h> pthread_mutex_t mutex=

PermissionError: [WinError 32] 另一個程式正在使用此檔案程序無法訪問。: 'C:\\Users\\ADMINI~1\\AppDa ta\\Local\\Temp\\pi

python3.6 安裝富途的量化包時出現: PermissionError: [WinError 32] 另一個程式正在使用此檔案,程序無法訪問。: ‘C:\Users\ADMINI~1\AppDa ta\Local\Temp\pip-build-_occom

linux C語言實現檔案之flock

一:flock函式特點: 1.flock只能加全域性鎖。 2.當一個程序用flock給一個檔案加鎖時,用另一個程序再給這個檔案加鎖,它會阻塞或者也可以返回加鎖失敗(可以自己設定)。 3.當給一個檔案加fcntl的獨佔鎖後,再給這個檔案加flock的獨佔鎖,其會進入阻塞狀態。

Linux學習筆記——程序間的通訊-檔案檔案

IPC(Inter-Process Communication,程序間通訊) 系統對檔案本身存在快取機制,使用檔案進行IPC的效率在某些多讀少寫的情況下並不低下 1.競爭條件(racing) 併發100個程序,約定好一個內容初值為0的檔案,每一個程序開

要點4C檔案操作

關於檔案操作個人比較困惑的地方有兩點: 1. 關於`w`和`wb`的區別 2. 如何定位檔案的讀寫位置 # 檔案格式和開啟模式 c中的檔案開啟模式分為:文字模式和二進位制模式,分別處理文字格式檔案和二進位制格式檔案。 **兩個模式的主要區別是在換行符的處理上**,利用文字模式在寫文字內容到檔案的時候,需

ping(NOIP模擬賽Round 4)第一次程序Rank 1!撒花慶祝!~(≧▽≦)/~

target 暴力 fin clas return ring freopen geo 是不是 原題傳送門 恩,就是裸的字符串處理啦。 連標程都打的是暴力(隨機數據太水啦!吐槽。) 本來O(n^2q)TLE好吧。、 然後我發明了一種神奇的算法,隨機數據跑的很快!,當然最壞復雜

奪命雷公狗C/C++-----4---頭文件的用法

png 文章 右鍵 com c++ nbsp 用法 -1 文件的 我們上一篇文章已經說過了如何創建項目,那麽我們這一篇就來說下頭文件的用法, 右鍵文件頭-----》添加----》新建項 然後我們就可以編寫我們的.h文件了,h說白了也就是類似head的意思。。 這

Ubuntu下用glade和GTK+開發C語言界面程序(一)

命令行 簡單的 暑假 all 位置 相同 write 3.0 面向對象的思想 前言:對於大學中計算機系的每年暑假的課設有太多想說的,能從中學到非常多東西,當然不排除打醬油的,這些能夠掠過哦,凡事都打醬油。人生也是打醬油的吧。2333。 對於大三曾經的課設一般的要求

J.U.C重入

itl 數據 cnblogs 執行 ont 微軟 nds asq jpg ReentrantLock重入鎖 ReentrantLock是Java並發包中互斥鎖,它有公平鎖和非公平鎖兩種實現方式, 重入的意思就是,如果已經獲得了鎖,如果執行期間還需要

程序5】 題目:利用條件運算符的嵌套來完成此題:學習成績>=90分的同學用A表示,60-89分之間的用B表示,60分以下的用C表示。 1.程序分析:(a>b)?a:b這是條件運算符的基本例子。

window code 例子 prompt 利用 學習 amp text span if…else語句相對比較多,但是容易理解 1 var scroe = window.prompt("請輸入1-100之間的數") 2 scroe = parseInt

【SignalR學習系列】4. SignalR廣播程序

back aspnet ocs || tutorial strong family load over 創建項目 創建一個空的 Web 項目,並在 Nuget 裏面添加 SignalR,jQuery UI 包,添加以後項目裏包含了 jQuery,jQuery.UI ,和

C# 編寫的winform程序的托盤功能

mouse name sso oid zed 程序 spa dll 鼠標 基本上大部分的桌面程序都有托盤功能,比如說QQ:當你單機QQ程序窗體的最小化按鈕時,窗體會消失,並且單擊電腦右下角的QQ圖標時,QQ的窗體重新顯現…… 在這裏介紹下我們自己編寫的winform程序怎麽

每天工作4小時的程序

oid 工作 5% com list andro and 程序 music aNDROID%E5%BC%80%E5%8F%91%E7%BE%A4%E9%9C%80%E8%A6%81%E7%9A%84%E5%8A%A0%E5%85%A5 http://music.hao12

C#自動更新本地程序

字節 xtra 版本 jobject key filename map images with 關於系統的自動更新。近日有一情況是需要將java端後臺最新版本的系統文件覆蓋本地客戶端,簡稱自動更新了。 本地會獲取當前系統的版本號去請求後臺java的接口數據。返回給我的是後臺

章節號比較排序(A.1、B.2.1、C.4

java 章節號 排序 private static int compareSerialNum(String str1,String str2){ if(str1.equals(str2)){ return 0; } if(!str1.contains(".")&

22、C#:窗體應用程序開發基本流程

c#在前面的內容中,主要介紹的是控制臺應用程序的開發,這節我們就來介紹下C#窗體應用程序的開發流程。1、打開sharp develop。2、選擇“文件”---》“新建”---》解決方案。3、接下來選擇:C#---》Windows應用程序---》Windows應用程序----》名稱和解決方案名稱 都為:“窗體應

c# 共享事件處理程序

使用 stat nbut c# 實例 一個 exceptio end exce 使用同一個方法來處理多個Button實例的Click事件。 1、全選所有的Button,在事件添加中的Click點擊事件中添加處理函數。 2、假如一個label控件用於顯示按鈕按下輸出文本 3

C#4.0新特性之協變與逆變實例分析

alt out thumb def 3.0 介紹 ted 路徑 運行 本文實例講述了C#4.0新特性的協變與逆變,有助於大家進一步掌握C#4.0程序設計。具體分析如下: 一、C#3.0以前的協變與逆變 如果你是第一次聽說這個兩個詞,別擔心,他們其實很常見。C#4.0中

c# 控制臺定時程序

key line timers 定制 監控 main object sin static using System; using System.Timers; namespace DaoChuCore2 { class Program {