c語言lock
① 【c語言】編寫ATM機程序
幫我用C語言編寫一個ATM取款程序要求代碼在300行以上
作為一個二十一世紀的大學生,要養成自己動手的習慣!不懂就去圖書館翻閱資料!雖然網上現在很
② 在linux中用C語言實現死鎖
讓我來告訴你答案!設置狀態變數lock=0,在佔用資源的函數中,設置lock=1;並在處理結束後設lock=0.
比如:
boollock=0;
intscan()
{
while(lock!=0);//循環檢測,直到資源釋放才執行下面的語句
lock=1;//鎖定資源
...//具體的執行掃描的語句
lock=1;//釋放資源
return0;
}
這個方法容易實現,但是佔用CPU,假定其他線程正在佔用掃描儀,那麼這個線程就會在自己的時間片內不停的執行while語句直到對方釋放掃描儀。由此造成了浪費。
現在流行的做法是通過中斷信號來做,那是一本書的內容,建議看linux內核編程方面的書。
③ 用單片機C語言控制6位密碼鎖。要求有一個清除鍵和確認鍵,密碼輸錯了會有報警音。請高手幫助了
我找到了一個,來自《51單片機C語言應用技術開發大全》
SCH圖正在繪制中。。。
#include <REGX51.H>//51單片機的頭文件
typedef unsigned char uchar; //類型定義,定義uchar類型
typedef unsigned int uint; //類型定義,定義uint 類型
//鍵盤子程序相關說明。
#define BLANKCHAR 10 //定義空白常量
#define PCHAR 11 //定義字元P常量
#define OPENCHAR 12 //定義開鎖字元常量
#define ALARMCHAR 13 //定義字元A常量
#define LINECHAR 14 //定義字元-常量
#define BACKKEY 0X0D //定義退格鍵常量
#define ENTERKEY 0X0F //定義確認鍵常量
#define LOCKKEY 0X0E //定義閉鎖鍵常量
#define NO_KEY 20 //定義無按鍵返回值
#define KEYPORT P2 //定義鍵盤埠
//Delay1Ms
void Delay1Ms()
{
uint i;
for (i=0;i<1000;i++);
}
//定義按鍵掃描碼表 按鍵掃描時,4位列線和4位行線組成位元組數據表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E,0X7D,0X7B,0X77};
uchar KeyPre; //保存上次掃描按鍵的鍵值
uchar KeyUp;
//用於控制按鍵去抖動操作。1:掃描時去抖動 2:等待釋放 3:釋放時去抖動。
#define LEDPORT P0 //定義顯示器段碼輸出埠
#define LEDCON P1 //定義顯示器位控制埠
uchar code SEGCODE[]=
{0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,// 0~9的共陽極代碼
0xff,//不顯示的共陽極段碼
0X8C,//字元P的共陽極段碼
0X8F,//┝的共陽極段碼
0X88,//字元A的共陽極段碼
0XBF,//字元-的共陽極段碼
};
//定義LED位碼控制碼
uchar code BITCODE[]={0Xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0X7f};
uchar DispBuf[6]; //保存顯示的字元
bit DispNormal; //控制顯示時,是正常顯示還是閃爍顯示。
uchar DispCnt; //控制閃爍顯示時的頻率。
#define SHORT_TIME 10 //蜂鳴器響200ms
#define LONG_TIME 100 //蜂鳴器響2s
#define LONGER_TIME 9000 //蜂鳴器響3 minutes
sbit ALARMCON=P3^4; //定義報警控制引腳
bit AlarmEnable; //是否報警或聲音提示
uint AlarmTime; //控制報警時間長度
sbit LOCKCON=P3^3; //定義電子鎖控制引腳
uchar code PassWord[]={1,2,3,4,5}; //定義初時密碼表
uchar PassInBuf[6]; //保存輸入的密碼字元
uchar PassPosi; //用戶輸入密碼字元存放在PassInBuf[]的位置。
bit TimerBit; //20ms定時時間到
uchar SysMode; //系統所處模式 0:輸入密碼模式 1:報警模式 2:開鎖模式
uchar ErrorCnt; //用戶連續輸入密碼出錯次數。
/*
入口參數:
FillChar:寫入緩沖區的字元
出口參數:無
*/
void Fill_Buf(uchar FillChar)
{
uchar i;
for(i=0;i<6;i++)
{
DispBuf[i]=FillChar;//用字元FillChar填充DispBuf[i]
PassInBuf[i]=FillChar; //用字元FillChar填充PassInBuf [i]
}
}
void Fill_Buf_P()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=PCHAR;// DispBuf[0]='P'
}
void Fill_Buf_O()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=OPENCHAR; // DispBuf[0]='┝'
}
void Fill_Buf_A()
{
Fill_Buf(LINECHAR); // DispBuf[1..5]= ' -----'
DispBuf[0]=ALARMCHAR; // DispBuf[0]='A'
}
/*
入口參數:
DispPosi:要顯示數據的LED號。
DispChar:要顯示的內容。
出口參數:無
*/
void Disp_Led_Sin(uchar DispChar,uchar DispPosi)
{
LEDPORT=SEGCODE[DispChar];//輸出顯示段碼
LEDCON&=BITCODE[DispPosi];//輸出顯示位碼
Delay1Ms(); //延時1MS
LEDCON|=0X3F;//關閉顯示器
}
/*(2)關閉顯示函數Disp_Led_OFF。
函數Disp_Led_OFF在顯示器上顯示空白字元,主要用在閃爍顯示。函數通過6次調用Disp_Led_Sin實現所需功能。代碼如下:*/
void Disp_Led_OFF()
{
uchar i;
LEDCON|=0X3F;// 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(BLANKCHAR,i);//逐個顯示空白字元
}
}
void Disp_Led_All()
{
uchar i;
LEDCON|=0X3F; // 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(DispBuf[i],i); //顯示DispBuf[]中的數值
}
}
void Disp_LED()
{
DispCnt++;
DispCnt%=10;
if(DispCnt==0)
{
DispNormal=~DispNormal;//200ms將閃爍顯示控制位取反
}
if(SysMode==1)
{//報警模式,閃爍顯示
if(!DispNormal)
{
Disp_Led_OFF();//顯示空白字元
return;
}
}
Disp_Led_All();//顯示DispBuf[]中的數值
}
/*
入口參數:
stime:蜂鳴器鳴叫時間。
出口參數:無
*/
void Sys_Speaker(uint stime)
{
AlarmEnable=1;//允許報警
AlarmTime=stime;//報警時間長短
}
void Sys_Alarm()
{
if(AlarmEnable==1)
{//允許報警
ALARMCON=0;//報警
AlarmTime--;
if(AlarmTime==0)
{//停止報警時間到
AlarmEnable=0;
ALARMCON=1;//禁止報警
if(SysMode==1)
{//報警發生在模式1時,要返回模式0
SysMode=0;
Fill_Buf_P();//顯示P
}
}
}
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Find_Key()
{
uchar KeyTemp,i;
KEYPORT=0xf0;//行線輸出0,列線輸出全1
KeyTemp=KEYPORT;//讀按鍵埠值
if(KeyTemp==0xf0)
return NO_KEY;//無鍵按下,返回
KEYPORT=KeyTemp|0x0f;//列線輸出,行線輸入
KeyTemp=KEYPORT;//讀取按鍵埠值
for(i=0;i<16;i++)
{
if(KeyTemp==KEYCODE[i])//根據按鍵埠掃描值,查找按鍵值
return i;//返回按鍵值
}
return NO_KEY;
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Scan_Key()
{
uchar KeyTemp;
KeyTemp=Find_Key();//掃描鍵盤,獲得按鍵值
if(KeyTemp==NO_KEY)
{
if(KeyUp<2)
{//無按鍵按下,返回
KeyUp=0;
return NO_KEY;
}
if(KeyUp==2)
{//按鍵要釋放,延時去抖動
KeyUp=3;
return NO_KEY;
}
if(KeyUp==3)
{//按鍵釋放,返回鍵值
KeyUp=0;
return KeyPre;
}
}
else
{
if(KeyUp==0)
{//有鍵按下,保存鍵值
KeyUp=1;
KeyPre=KeyTemp;
}
else if(KeyUp==1)
{//去抖動後,再次測到有按鍵按下
if( KeyPre==KeyTemp)
KeyUp=2;
else
KeyPre=KeyTemp;
} else if(KeyUp==3)
{//等待按鍵釋放
KeyUp=2;
}
}
return NO_KEY;
}
/*
入口參數:
Key:按鍵值
出口參數:無
*/
void Key_Process(uchar Key)
{
uchar i;
if(Key==NO_KEY)
return ;//無按鍵,不處理
switch(SysMode)
{
case 0://輸入密碼
switch(Key)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
DispBuf[PassPosi]=LINECHAR;//顯示'-'
PassInBuf[PassPosi]=Key;//保存用戶輸入的密碼
if(PassPosi<5)
PassPosi++;//調整密碼輸入位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case BACKKEY://退格鍵
DispBuf[PassPosi]=BLANKCHAR;//顯示' '
PassInBuf[PassPosi]=BLANKCHAR;//清除當前位置的密碼
if(PassPosi>1)
PassPosi--;//調整顯示位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case ENTERKEY://確定按鍵
for(i=0;i<5;i++)
{//比較用戶輸入密碼與系統預設密碼是否一致
if(PassInBuf[i+1]!=PassWord[i])
break;
}
if(i>=5)
{//輸入密碼正確
Fill_Buf_O();//顯示開鎖狀態
PassPosi=1;
LOCKCON=1;//開鎖
ErrorCnt=0;
Sys_Speaker(LONG_TIME);//發長提示音
SysMode=2;//轉模式2
}
else
{
ErrorCnt++;//出錯次數加一
if(ErrorCnt>2)
{//次數超過3次
ErrorCnt=0;
Fill_Buf_A();//顯示報警狀態
PassPosi=1;
Sys_Speaker(LONGER_TIME);//發報警音
SysMode=1;
}
else
{//出錯次數少於3次,用戶重新輸入
Fill_Buf_P();
PassPosi=1;
Sys_Speaker(LONG_TIME);
}
}
break;
case LOCKKEY://閉鎖鍵
Fill_Buf_P();//顯示P
PassPosi=1;
Sys_Speaker(SHORT_TIME);
break;
}
break;
case 2://開鎖狀態
if(Key==LOCKKEY)
{//用戶按動閉鎖按鍵
Fill_Buf_P();
SysMode=0;
LOCKCON=0;//閉鎖
Sys_Speaker(SHORT_TIME);
}
break;
}
}
void Ini_Timer0()
{
TMOD&=0XF0;
TMOD|=0X01;// 初始化T0,模式1
TR0=0;
TH0=(65536-20000)/256;//T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;//啟動T0
ET0=1;//允許T0中斷
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-20000)/256; //T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;
TimerBit=1;//定時時間到
}
void Ini_System()
{
PassPosi=1;
LOCKCON=0;//閉鎖
Ini_Timer0();//初始化T0
Fill_Buf_P();
EA=1;//允許系統中斷
}
void main()
{
uchar KeyTemp;
Ini_System();
while(1)
{
if (TimerBit==1)
{//定時時間到
Disp_LED();//刷新顯示器
Sys_Alarm();//報警處理
KeyTemp=Scan_Key();//掃描按鍵
Key_Process(KeyTemp);//按鍵處理
TimerBit=0;
}
}
}
④ 用c語言寫個 socket tcp 的
#include <winsock2.h>
#include <stdio.h>
#include <pthread.h>
#pragma comment(lib,"ws2_32.lib")
typedef struct{
SOCKET accpt;
int lock;
}Arg;
void *transfer(void *arg)
{
Arg * info = (Arg *)arg;
SOCKET clientSock;
char recvbuf[102];
char sendBuf[] = "10";
int ret;
memcpy(&clientSock,(void*)&info->accpt,sizeof(clientSock));
info->lock =1;
while (TRUE)
{
ret = send(clientSock,sendBuf,2,0);
if (ret == -1)
{
break;
}
ret = recv(clientSock,recvbuf,102,0);
printf("%s ",recvbuf);
}
return (void *)0;
}
void* timer(void *arg)
{
time_t last = time(NULL);
time_t now;
int i = 20;
while(i--)
{
now = time(NULL);
if(now - last == 1)
{
printf("1s past! ");
last = now;
}
Sleep(500);
}
printf("timer exit. ");
return (void *)0;
}
int main(void) {
WSADATA wsaData;
SOCKET ListenSocket;
SOCKADDR_IN service,client;
int len = sizeof(client);
Arg argument;
pthread_t tid;
char sendBuf[] = "ID=2;WHAT=host";
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("Error at WSAStartup() ");
return 1;
}
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld ", WSAGetLastError());
WSACleanup();
return 1;
}
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27115);
if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed. ");
closesocket(ListenSocket);
WSACleanup();
return 1;
}
if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
printf("Error listening on socket. ");
closesocket(ListenSocket);
WSACleanup();
return 1;
}
argument.lock = 1;
printf("Waiting for client to connect... ");
pthread_create(&tid,NULL,timer,NULL);
while(TRUE){
argument.accpt = accept( ListenSocket, (SOCKADDR*)&client, &len );
if (argument.accpt == INVALID_SOCKET) {
printf("accept failed: %d ", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
} else {
printf("accept%s:%d ",inet_ntoa(client.sin_addr),client.sin_port);
while (!argument.lock);
argument.lock = 0;
// sendto(argument.accpt,sendBuf,sizeof(sendBuf),0,(SOCKADDR*)&client,len);
pthread_create(&tid,NULL,transfer,&argument);
//send(AcceptSocket,sendBuf,sizeof(sendBuf),0);
}
}
// No longer need server socket
closesocket(ListenSocket);
WSACleanup();
return 0;
}
發送數據格式按需求。可以發送字元串,也可以發送結構體。如果發送結構體的話,要注意序列化和反序列化。程序例子是伺服器對每個客戶端的connect動作起一個線程去交互。還有一個線程是定時器。
⑤ C語言緩沖區在哪裡
緩沖區具體在哪裡是與操作系統、編譯器相關的
以VC++為例。察看getchar的源代碼(src\fgetchar.c),有:
int __cdecl _fgetchar (void){
return(getc(stdin));
}
#undef getchar
int __cdecl getchar (void){
return _fgetchar();
}
可見getchar()相當於getc(stdin)
繼續察看getc(src\fgetc.c),有一段(為便於閱讀,有刪減):
int __cdecl getc (FILE *stream){
int retval;
_ASSERTE(stream != NULL);
_lock_str(stream);
__try {
retval = _getc_lk(stream);
}
__finally {
_unlock_str(stream);
}
return(retval);
}
這段代碼里_lock_str其實是通過Win32 API提供的臨街區來鎖住文件
接收用戶輸入發生在_getc_lk,_getc_lk宏調用_filbuf。_filbuf在_filbuf.c中可以查看,這段代碼比較長,就不貼出來了
_filbuf主要是調用了_read(_fileno(stream), stream->_base, stream->_bufsiz)
而_read最終則是調用了Win32API ReadFile,以下是用WinDbg輸出的getchar的調用棧:
# ChildEBP RetAddr
00 0012fe6c 0040a4e7 kernel32!ReadFile
01 0012fea8 0040a3b9 TestStruct!_read_lk+0x107 [read.c @ 146]
02 0012fec0 00403140 TestStruct!_read+0x69 [read.c @ 75]
03 0012fee8 00401290 TestStruct!_filbuf+0xd0 [_filbuf.c @ 127]
04 0012ff08 004012cc TestStruct!fgetc+0x80 [fgetc.c @ 44]
05 0012ff14 0040103d TestStruct!getc+0xc [fgetc.c @ 56]
06 0012ff20 00401058 TestStruct!_fgetchar+0xd [fgetchar.c @ 37]
07 0012ff28 0040101e TestStruct!getchar+0x8 [fgetchar.c @ 47]
08 0012ff80 0040115c TestStruct!main+0xe [d:\my programs\teststruct\ts.cpp @ 4]
09 0012ffc0 7c816fe7 TestStruct!mainCRTStartup+0xfc [crt0.c @ 206]
0a 0012fff0 00000000 kernel32!BaseProcessStart+0x23
可見,getchar最終調用了ReadFile。關於ReadFile的原理以及緩沖區在哪裡,請你再提一個問我再回答