一、在linux平台下,每个线程可有专用数据:

#include <pthread.h>

#include <stdio.h>
struct mydata{
int x;
char c[4];
};
pthread_t pthreada,pthreadb;
pthread_key_t datakey;//每个进程创建一次,不同的线程,同样名字的键指向不同的地方

void cleanup_mydata(void dataptr){//删除键时调用的
free((struct mydata
)dataptr);
}
void anum1(){
int rc;
struct mydata mdata=(struct mydata)malloc(sizeof(struct mydata));
mdata->x=1;
mdata->c[0]=‘a’;
mdata->c[1]=’\0’;
rc=pthread_setspecific(datakey,(void
)mdata);//设置键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存
sleep(1);
struct mydata mmdata=(struct mydata)pthread_getspecific(datakey);//取出键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存
printf("-%d-%s\n",mmdata->x,mmdata->c);
fflush(stdout);
}
void bnum2(){
int rc;
struct mydata mdata=(struct mydata)malloc(sizeof(struct mydata));
mdata->x=2;
mdata->c[0]=‘b’;
mdata->c[1]=’\0’;
rc=pthread_setspecific(datakey,(void*)mdata);//设置键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存
sleep(1);
struct mydata mmdata=(struct mydata)pthread_getspecific(datakey);//取出键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存
printf("-%d-%s\n",mmdata->x,mmdata->c);
fflush(stdout);
}

int main(void){

int rc;rc=pthread_key_create(&datakey,cleanup_mydata);//为键删除时的清理函数
pthread_create(&pthreada,NULL,anum1,NULL);
pthread_create(&pthreadb,NULL,bnum2,NULL);
sleep(3);
pthread_join(pthreada,NULL);
pthread_join(pthreadb,NULL);
rc=pthread_key_delete(datakey); //仅删除键,但不删除值指向的内存,线程终止调用用户自定义的删除函数,本例中为cleanup_mydata

}
二、摸拟shell

通过execlp函数来实现 ,execlp函数用于执行文件

其参数与说明为:

#include <process.h>

int execlp( const char file,
const char arg0,
const char arg1,

const char argn,
NULL );
file,
const char arg0,
const char arg1,

const char * argn,
NULL );
Arguments:
file

Used to construct a pathname that identifies the new process image file. If the fileargument contains a slash character, the file argument is used as the pathname for the file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable PATH.

arg0, …, argn

Pointers to NULL-terminated character strings. These strings constitute the argument list available to the new process image. Terminate the list terminated with a NULL pointer. The arg0 argument must point to a filename that’s associated with the process.

waitpid()
wait for process termination

Function
SYNOPSIS DESCRIPTION PARAMETERS RETURN VALUES CONFORMANCE MULTITHREAD SAFETY LEVEL PORTING ISSUES AVAILABILITY SEE ALSO
SYNOPSIS
#include <sys/types.h>

#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *stat_loc, int options);

DESCRIPTION
The waitpid() function lets the calling process obtain status information about one of its child processes. If status information is available for two or more child processes, the order in which their status is reported is unspecified. If more than one thread is suspended in waitpid() awaiting termination of the same process, exactly one thread returns the process status at the time of the target child process termination. The other threads return -1, with errno set to ECHILD.

If the calling process sets SIGCHLD to SIG_IGN, and the process has no unwaited for children that were transformed into zombie processes, the calling thread blocks until all of the children of the process terminate, at which time waitpid() returns -1 with errno set to ECHILD.

If the parent process terminates without waiting for all of its child processes to terminate, the remaining child processes are assigned a new parent process ID corresponding to a system-level process.

PARAMETERS

pid

Specifies a set of child processes for which the status is requested:

If pid is equal to -1, status is requested for any child process. In this respect, waitpid() is equivalent to wait().
If pid is greater than 0, it specifies the process ID of a single child process for which status is requested.
If pid is 0, status is requested for any child process whose process group ID is equal to that of the calling process. This setting is not currently supported.
If pid is less than -1, status is requested for any child process whose process group ID is equal to the absolute value of pid. This setting is not currently supported.

stat_loc

Specifies the location to which the child process’ exit status is stored. If NULL is passed, no exit status is returned. Otherwise, the following macros defined in <sys/wait.h> can be used to evaluate the returned status:

WIFEXITED(s)

Evaluates to a non-zero value if status was returned for a child process that exited normally.

WEXITSTATUS(s)

If the value of WIFEXITED(s) is non-zero, this macro evaluates to the low-order 8 bits of the status argument that the child process passed to exit() or _exit(), or to the value that the child process returned from main().

WIFSIGNALED(s)

Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught.

WTERMSIG(s)

If the value of WIFSIGNALED(s) is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.

WIFCORED(s)

Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught, and whose default action is to dump core.

WCOREDUMP(s)

Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught, and whose default action is to dump core.

WCORESIG(s)

If the value of WIFCORED(s) is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.

WIFSTOPPED(s)

Evaluates to a non-zero value if status was returned for a child process that is currently stopped.

WSTOPSIG(s)

If the value of WIFSTOPPED(s) is non-zero, this macro evaluates to the number of the signal that caused the child process to stop.

options

Is the bitwise inclusive-OR of zero or more of the following flags, defined in <sys/wait.h>:

WNOHANG

The waitpid() function does not suspend execution of the calling thread if status is not immediately available for one of the child processes specified by pid.

WUNTRACED

The status of any child processes specified by pid that are stopped, and whose status has not yet been reported since they stopped, is also reported to the requesting thread. This value is currently not supported, and is ignored.

RETURN VALUES
If waitpid() was invoked with WNOHANG set in options, and there are children specified by pid for which status is not available, waitpid() returns 0. If WNOHANG was not set,waitpid() returns the process ID of a child when the status of that child is available. Otherwise, it returns -1 and sets errno to one of the following values:

ECHILD

The process or process group specified by pid does not exist or is not a child of the calling process.

EFAULT

stat_loc is not a writable address.

EINTR

The function was interrupted by a signal. The value of the location pointed to by stat_loc is undefined.

EINVAL

The options argument is not valid.

ENOSYS

pid specifies a process group (0 or less than -1), which is not currently supported.

程序如下:

#include <stdio.h>
#include <sys/wait.h>

#define MAXLINE 100
//execlp模拟SHELL

int main(void){
int pid;
int jg,status,len;
char buf[MAXLINE];

printf("\n##myhaspl~~");//自定义的shell提示符
while(fgets(buf,MAXLINE,stdin)!=NULL){//读入一行
len=strlen(buf)-1;
if (buf[len]’\n’){ //去除换行符,execlp只接受以NULL结尾
buf[len]=0;
}
pid=fork();
if (pid<0){
printf(“fork error!\n”);
}
else if (pid0){//子进程
printf("\n");
if (buf[0]‘Q’&&strlen(buf)1){//键入Q表示退出shell
exit(200);
}
jg=execlp(buf,buf,(char *)0);
if (jg-1){//错误
printf(“不能执行:%s\n”,buf);
exit(127);
}
exit(0);
}
if ((jgwaitpid(pid,&status,0))<0){//父进程
printf(“waitpid error\n”);
}
if (WEXITSTATUS(status)==200) {//WEXITSTATUS计算返回值
printf(“退出…\n”);
break;
}
printf("\n##myhaspl~~");//自定义的shell提示符
}
exit(0);
}
执行:
deepfuture@deepfuture-laptop:~/private/mytest$ gcc -o test21 test21.c
test21.c: In function ‘main’:
test21.c:15: warning: incompatible implicit declaration of built-in function ‘strlen’
test21.c:26: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:28: warning: incompatible implicit declaration of built-in function ‘execlp’
test21.c:31: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:33: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:44: warning: incompatible implicit declaration of built-in function ‘exit’
deepfuture@deepfuture-laptop:~/private/mytest$ ./test21

##myhaspl~~ls

1 pvmtest test20 testbswap testmul.s x
ex.txt test test20.c testbswap.s testmutex x.c
gmon.out test12.s test21 test.c testmutex.c xx
hello test13 test21.c test.c~ testpopen xx.c
hello.c test13.c test2.c testmes testpopen.c xx.txt
hello.o test15 test6 testmes.c testpvm1.c xxx.txt
hello.s test15.c test66 testmesrecv testpvm2.c xxxx.txt
main test19 test66.s testmesrecv.c testpx xy
main.c test19.c test6.c testmessnd testpx1
main.c~ test1.c testasmc testmessnd.c testpx1.s
myhello.txt test2 testasmc.c testmul testpx.s

##myhaspl~~xx

不能执行:xx

##myhaspl~~Q

退出…

knoppix@Microknoppix:/mnt-system/lx/test$ gcc -D_REENTRANT -lpthread -o testcondout testcondout.c
knoppix@Microknoppix:/mnt-system/lx/test$ ./testcondout

please input an integer:(<=1000)26
time out
time out
1/1 finished,push 1.0000000000
1/2 finished,push 0.5000000000
1/3 finished,push 0.3333333333
1/4 finished,push 0.2500000000
1/5 finished,push 0.2000000000
time out
1/6 finished,push 0.1666666667
1/7 finished,push 0.1428571429
1/8 finished,push 0.1250000000
1/9 finished,push 0.1111111111
1/10 finished,push 0.1000000000
time out
1/11 finished,push 0.0909090909
1/12 finished,push 0.0833333333
1/13 finished,push 0.0769230769
1/14 finished,push 0.0714285714
1/15 finished,push 0.0666666667
1/1:1.0000000000 added result 1.0000000000
1/2:0.5000000000 added result 1.5000000000
1/3:0.3333333333 added result 1.8333333333
1/4:0.2500000000 added result 2.0833333333
1/5:0.2000000000 added result 2.2833333333
1/6:0.1666666667 added result 2.4500000000
1/7:0.1428571429 added result 2.5928571429
1/8:0.1250000000 added result 2.7178571429
1/9:0.1111111111 added result 2.8289682540
1/10:0.1000000000 added result 2.9289682540
1/11:0.0909090909 added result 3.0198773449
1/12:0.0833333333 added result 3.1032106782
1/13:0.0769230769 added result 3.1801337551
1/14:0.0714285714 added result 3.2515623266
1/15:0.0666666667 added result 3.3182289932
1/1:1.0000000000 computed result 1.0000000000
1/2:0.5000000000 computed result 0.5000000000
1/3:0.3333333333 computed result 0.8333333333
1/4:0.2500000000 computed result 0.5833333333
1/5:0.2000000000 computed result 0.7833333333
1/6:0.1666666667 computed result 0.6166666667
1/7:0.1428571429 computed result 0.7595238095
1/8:0.1250000000 computed result 0.6345238095
1/9:0.1111111111 computed result 0.7456349206
1/10:0.1000000000 computed result 0.6456349206
1/11:0.0909090909 computed result 0.7365440115
1/12:0.0833333333 computed result 0.6532106782
1/13:0.0769230769 computed result 0.7301337551
1/14:0.0714285714 computed result 0.6587051837
1/15:0.0666666667 computed result 0.7253718504
=====compute finish!= result:0.7253718504
1/16 finished,push 0.0625000000
1/17 finished,push 0.0588235294
1/18 finished,push 0.0555555556
1/19 finished,push 0.0526315789
1/20 finished,push 0.0500000000
1/16:0.0625000000 added result 3.3807289932
1/17:0.0588235294 added result 3.4395525226
1/18:0.0555555556 added result 3.4951080782
1/19:0.0526315789 added result 3.5477396571
1/20:0.0500000000 added result 3.5977396571
1/21 finished,push 0.0476190476
1/22 finished,push 0.0454545455
1/23 finished,push 0.0434782609
1/24 finished,push 0.0416666667
1/25 finished,push 0.0400000000
time out
1/16:0.0625000000 computed result 0.6628718504
1/17:0.0588235294 computed result 0.7216953798
1/18:0.0555555556 computed result 0.6661398242
1/19:0.0526315789 computed result 0.7187714032
1/20:0.0500000000 computed result 0.6687714032
1/21:0.0476190476 computed result 0.7163904508
1/22:0.0454545455 computed result 0.6709359053
1/23:0.0434782609 computed result 0.7144141662
1/24:0.0416666667 computed result 0.6727474995
1/25:0.0400000000 computed result 0.7127474995
=====compute finish!= result:0.7127474995
1/21:0.0476190476 added result 3.6453587048
1/22:0.0454545455 added result 3.6908132502
1/23:0.0434782609 added result 3.7342915111
1/24:0.0416666667 added result 3.7759581778
1/25:0.0400000000 added result 3.8159581778
1/26 finished,push 0.0384615385
time out
time out
1/26:0.0384615385 computed result 0.6742859611
=====compute finish!= result:0.6742859611
1/26:0.0384615385 added result 3.8544197162
====add finish! result:3.8544197162

2个线程完成累加和累加减运算(其中一个采用超时等待条件信号,另一个采用等待条件信号),n个线程完成计算每个符点数

#include <pthread.h>  #include <bits/pthreadtypes.h>  #include <stdio.h>  #include <stdlib.h>  #include <errno.h> #define MAXS 1000   #define MAXTDS 5 //线程池大小double myjg[MAXS+1];//计算结果存放位置
int max;
pthread_mutex_t eventlock;   //互斥锁
pthread_cond_t myevent;   //条件变量
pthread_t threads[MAXTDS+2];   //线程池,完成1/n计算
int isend=0;int done;    void mycomp(void x){//计算1/i的结果,计算结果放在一个数组中。  int i=0;int rc;while (1){
pthread_mutex_lock(&eventlock);
if (isend){pthread_mutex_unlock(&eventlock); break;
}
i=myjg[0];//myjg[0]存放着线程已经计算到的i。
if (i<max){i++;myjg[0]=i;
}  if (i==max){//最后一个数myjg[i]=(1/(double)i);isend=1; printf("1/%d finished,push %.10f\n",i,myjg[i]); fflush(stdout);pthread_mutex_unlock(&eventlock); sleep(3);rc=pthread_cond_signal(&myevent);//广播信号,多个任务不被阻塞,多个任务竞争互斥锁的所有权。也可以使用pthread_cond_signal(&event);发送信号,这样只有一个线程不被阻塞,其它线程都被阻塞。if (rc){perror("pthread_cond_broadcast");fflush(stdout);}  sleep(2);  break;     }//开始计算myjg[i]=(1/(double)i);  printf("1/%d finished,push %.10f\n",i,myjg[i]); fflush(stdout); pthread_mutex_unlock(&eventlock);   if (!(i%MAXTDS)){sleep(3); pthread_cond_broadcast(&myevent);//广播信号,多个任务不被阻塞,多个任务竞争互斥锁的所有权。也可以使用pthread_cond_signal(&event);发送信号,这样只有一个线程不被阻塞,其它线程都被阻塞。    sleep(3); }
}
pthread_exit(NULL);
}  void myprint1(void xx){//读取数组,将计算结果累加,最终完成1/1+1/2+1/3+......+1/n的计算,使用超时等待  int maxi;  int curj=1;  double jg=0; int rc; struct timeval now;//使用微秒struct timespec timeout;  //使用纳秒while(curj<=max)  {  //取当前时间// myhaspl gettimeofday(&now);//准备时间间隔timeout.tv_sec=now.tv_sec+1;timeout.tv_nsec=now.tv_usec*1000;maxi=0;pthread_mutex_lock(&eventlock);//用于条件变量的互斥,条件变量就是一个用来发送事件发生信号的信号量rc=pthread_cond_timedwait(&myevent,&eventlock,&timeout);//在等待条件变量myevent的发生,超时就返回,不再等待。条件变量必须与一个互斥锁eventlock相关联,条件变量不提供锁定,必须有一个互斥锁eventlock配合。//互斥锁eventlock在调用wait前应锁定,然后在wait期间,互斥量eventlock被解锁。挂起线程执行,直到条件变量myevent收到信号             if (rc==0){  // myhasplmaxi=myjg[0]; fflush(stdout); pthread_mutex_unlock(&eventlock);for (;curj<=maxi;curj++){    // myhaspljg+=myjg[curj];  printf("1/%d:%.10f added result %.10f\n",curj,myjg[curj],jg);     fflush(stdout);                }   } else if (rc==ETIMEDOUT){//TIMEOUTprintf("time out\n");fflush(stdout); pthread_mutex_unlock(&eventlock); continue;            } else  {  // myhasplperror("pthread_cond_wait");fflush(stdout); pthread_mutex_unlock(&eventlock); continue;              }}  printf("================add finish!============ result:%.10f\n",jg);//输出累加结果。  fflush(stdout);pthread_exit(NULL);
}  void myprint2(void xx){//读取数组,将计算结果完成1/1+1/2-1/3+1/4-1/5......的计算  int maxi=0;  int curi=1;  double jg=0; int fh=1;int rc; while(curi<=max)  {  maxi=0;sleep(2); pthread_mutex_lock(&eventlock);//用于条件变量的互斥,条件变量就是一个用来发送事件发生信号的信号量rc=pthread_cond_wait(&myevent,&eventlock);//在等待条件变量myevent的发生。条件变量必须与一个互斥锁eventlock相关联,条件变量不提供锁定,必须有一个互斥锁eventlock配合。//互斥锁eventlock在调用wait前应锁定,然后在wait期间,互斥量eventlock被解锁。挂起线程执行,直到条件变量myevent收到信号
// myhasplif (rc==0){maxi=myjg[0]; fflush(stdout); pthread_mutex_unlock(&eventlock);while (curi<=maxi){              jg+=fh*myjg[curi];  printf("***1/%d:%.10f computed result %.10f\n",curi,myjg[curi],jg);  fflush(stdout);       fh=-fh;curi++;}                 printf("===============compute finish!=========== result:%.10f\n",jg);//输出累加结果 fflush(stdout);              } else{//errorperror("pthread_cond_wait");fflush(stdout); pthread_mutex_unlock(&eventlock); continue;            }  }      pthread_exit(NULL);
}  int main(){  //计算1+1/2+1/3+......和1+1/2-1/3+1/4-1/5......  pthread_mutex_init(&eventlock,NULL);pthread_cond_init(&myevent,NULL);         int i =0;printf("please input an integer:(<=%d)",MAXS);  while (scanf("%d",&max),max>MAXS){//n的最大值  printf("please input an integer:(<=%d)",MAXS);  };  //myhasplmyjg[0]=0;pthread_create(&(threads[i]),NULL,myprint1,(void )&i);sleep(1); i++;      pthread_create(&(threads[i]),NULL,myprint2,(void )&i);  sleep(1);  i++; for (;i<=MAXTDS;i++){  pthread_create(&(threads[i]),NULL,mycomp,(void )&i);  sleep(1);        }   sleep(MAXTDS2*(i/10+1));  //wait......pthread_mutex_destroy(&eventlock);    return(0);
}   一、端口1、0-1023:预留端口,超级用户使用2、1024-49151:已经注册的端口号3、49152-65535:可自由使用的端口或动态端口二、套接字类型1、SOCK_STREAM(字节流套接字):面向连接,可靠的全双工字节流。对于AF_INET来说,建立TCP连接2、SOCK_DGRAM(数据报套接字):不保证数据正确分发,不保证发送数据的训序。对于AF_INET来说,建立UDP连接3、SOCK_RAW(原始套接字)三、建立套接字int fd;fd=socket(AF_INET,SOCK_STREAM,0);//除使用SOCK_RAW外,最后一个protocol被设置为0,AF_INET为套接口四、应用 1.serverdeepfuture@deepfuture-laptop:~/private/mytest$ ./testtcps
server wait....
............................
server read :myhasplserver send :hello
.....
server read :myhasplserver send :hello
2.client
deepfuture@deepfuture-laptop:~/private/mytest$ ./testtcpc
client send....
client send :myhasplclient read :hellodeepfuture@deepfuture-laptop:~/private/mytest$ ./testtcpc
client send....
client send :myhasplclient read :hellodeepfuture@deepfuture-laptop:~/private/mytest$ 3.source
1)server
C代码
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
//myhaspl
ssize_t readn(int fd,void ptr,size_t maxcn){//读取n个字符,maxc为读取的数目  size_t noreadcn,readcn;  char buf=ptr;  noreadcn=maxcn;  while(noreadcn>0){  if ( (readcn=read(fd,buf,noreadcn))<0){//读数据  if (errno==EINTR) {//数据读取前,操作被信号中断  perror("中断错误");  readcn=0;             }  else {return -1;}//无法修复错误,返回读取失败  }  else if(readcn==0) break;//EOF  noreadcn-=readcn;//读取成功,但是如果读取的字符数小于maxc,则继续读,因为可能数据还会继续通过网络送过来      buf+=readcn;    if (buf==0) break;//如果读到字符串结尾标志则退出,必须有这句,否则会死循环  }    return (maxcn-noreadcn);
}  ssize_t  writen(int fd,void ptr,size_t maxcn){//写入n个字符  size_t nowritecn,writecn;  char buf=ptr;  nowritecn=maxcn;  while(nowritecn>0){  if((writecn=write(fd,buf,nowritecn))<=0){//写数据  if (errno==EINTR) {//数据写前,操作被信号中断  perror("中断错误");  writecn=0;               }  else {return -1;}//无法修复错误,返回读取失败  }  nowritecn-=writecn;  buf+=writecn;    }   return (maxcn-nowritecn);
}  int main(void){  int fd;  int addresslen;  struct sockaddr_in address;//地址信息结构  int pid;  int rc;  fd_set fdset;  //建立socket  fd=socket(AF_INET,SOCK_STREAM,0);//fd为socket  if (fd==-1){//错误,类型从errno获得  perror("error");//perror先输出参数,后跟":"加空格,然后是errno值对应的错误信息(不是错误代码),最后是一个换行符。          }  //bind 到socket fd      address.sin_family=AF_INET;//IPV4协议,AF_INET6是IPV6  address.sin_addr.s_addr=htonl(INADDR_ANY);//l表示32位,htonl能保证在不同CPU的相同字节序  address.sin_port=htons(1253);//端口号,s表示16位  addresslen=sizeof(address);  bind(fd,(struct sockaddr )&address,addresslen);//bind  //建立socket队列,指定最大可接受连接数  rc=listen(fd,32);//最多接收32个连接,开始监听  //int listen(int sockfd, int backlog)返回:0──成功, -1──失败  //内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接  if (rc==-1) {  perror("listen error");//监听失败  exit(1);  }  printf("server wait....\n");             while(1){  struct sockaddr_in clientaddress;  int address_len;  int client_sockfd;  char mybuf[100];      char buf="hello\n";    struct timeval timeout;//超时结构体  //超时为2秒  timeout.tv_sec=1;  timeout.tv_usec=0;  //设置fdset  FD_ZERO(&fdset);//清除fdset  FD_CLR(fd,&fdset);//清除fd的标志  FD_SET(fd,&fdset);//设置标志  //select  if ((select(fd+1,&fdset,NULL,NULL,&timeout))<0){  perror("select error");  fflush(stdout);                }  //等待连接,使用新的进程或线程来处理连接  fflush(stdout);       address_len=sizeof(clientaddress);                if(FD_ISSET(fd,&fdset)){  //如果有连接到来  client_sockfd=accept(fd,(struct sockaddr )&clientaddress,&address_len);//client_sockfd可理解为一个文件句柄,能用read和write操作。client_address是客户端信息结构 myhaspl  //fork进程来处理每个客户的连接        pid=fork();  if (pid<0){//错误  printf("error:%s\n",strerror(errno));//strerror将errno映射为一个错误信息串 myhaspl  close(client_sockfd);  exit(1);   }     if (pid==0){ //子进程处理每个客户端的数据              close(fd);//子进程关闭不需要它处理的监听资源  //读取数据 myhaspl  bzero(mybuf,100);                     readn(client_sockfd,(void )mybuf,100);  printf("\nserver read :%s",mybuf);                    //发送数据                    writen(client_sockfd,(void )buf,strlen(buf)+1);                 printf("\nserver send :%s",buf);                  close(client_sockfd);  exit(0);  }  else {//父进程  close(client_sockfd);//父进程不处理客户端连接,因此关闭,但并不意味着把子进程的处理句柄关闭,因为子进程继承了父进程的client_sockfd资源         myhaspl       }                                 }else{  printf(".");  fflush(stdout);  }  }
}  2) client
C代码
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
//myhaspl
ssize_t readn(int fd,void ptr,size_t maxcn){//读取n个字符,maxc为读取的数目  size_t noreadcn,readcn;  char buf=ptr;  noreadcn=maxcn;  while(noreadcn>0){  if ( (readcn=read(fd,buf,noreadcn))<0){//读数据  if (errno==EINTR) {//数据读取前,操作被信号中断 myhaspl  perror("中断错误");  readcn=0;              }  else {return -1;}//无法修复错误,返回读取失败  }  else if(readcn==0) break;//EOF myhaspl  noreadcn-=readcn;//读取成功,但是如果读取的字符数小于maxc,则继续读,因为可能数据还会继续通过网络送过来      buf+=readcn;     if (buf==0) break;    //如果读到字符串结尾标志则退出,必须有这句,否则会死循环  myhaspl  }     return (maxcn-noreadcn);
}  ssize_t writen(int fd,void ptr,size_t maxcn){//写入n个字符  size_t nowritecn,writecn;  char buf=ptr;  nowritecn=maxcn;  while(nowritecn>0){  if((writecn=write(fd,buf,nowritecn))<=0){//写数据  if (errno==EINTR) {//数据写前,操作被信号中断  perror("中断错误");  writecn=0;               }  else {return -1;}//无法修复错误,返回读取失败  }  nowritecn-=writecn;  buf+=writecn;   }    return (maxcn-nowritecn);
}  int main(void){  int fd;  int addresslen;  struct sockaddr_in address;//地址信息结构 myhaspl  int pid;  char mybuf[100];          char buf="myhaspl\n";  int rc;  fd=socket(AF_INET,SOCK_STREAM,0);//建立socket  if (fd==-1){//错误,类型从errno获得  perror("error");//perror先输出参数,后跟":"加空格,然后是errno值对应的错误信息(不是错误代码),最后是一个换行符。    myhaspl       }  printf("client send....\n");  fflush(stdout);  //连接  address.sin_family=AF_INET;//IPV4协议,AF_INET6是IPV6 myhaspl  address.sin_addr.s_addr=inet_addr("127.0.0.1");//l表示32位,htonl能保证在不同CPU的相同字节序  address.sin_port=htons(1253);//端口号,s表示16位 myhaspl  addresslen=sizeof(address);          rc=connect(fd,(struct sockaddr )&address,addresslen);//连接服务器 myhaspl  if (rc==-1){//rc=0成功,rc=-1失败 myhaspl  perror("连接错误");  exit(1);  }  //发送数据   writen(fd,(void )buf,strlen(buf)+1);  printf("client send :%s\n",buf);        //读取数据  bzero(mybuf,100);    readn(fd,(void *)mybuf,100);   printf("client read :%s\n",mybuf);   close(fd);  exit(0);                  }  线程池共享内存+信号量
deepfuture@deepfuture-laptop:~/private/mytest$ gcc -std=gnu99 -o testshm testshm.c
testshm.c: In function ‘main’:
testshm.c:38: warning: implicit declaration of function ‘semget’
testshm.c:41: warning: implicit declaration of function ‘exit’
testshm.c:41: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:45: warning: implicit declaration of function ‘semctl’
testshm.c:48: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:51: warning: implicit declaration of function ‘shmget’
testshm.c:54: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:57: warning: implicit declaration of function ‘shmat’
testshm.c:60: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:63: warning: implicit declaration of function ‘memset’
testshm.c:63: warning: incompatible implicit declaration of built-in function ‘memset’
testshm.c:69: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:78: warning: implicit declaration of function ‘strlen’
testshm.c:78: warning: incompatible implicit declaration of built-in function ‘strlen’
testshm.c:85: warning: implicit declaration of function ‘memcpy’
testshm.c:85: warning: incompatible implicit declaration of built-in function ‘memcpy’
testshm.c:92: warning: implicit declaration of function ‘semop’
testshm.c:95: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:119: warning: incompatible implicit declaration of built-in function ‘strlen’
testshm.c:124: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:132: warning: implicit declaration of function ‘wait’
testshm.c:134: warning: implicit declaration of function ‘shmdt’
testshm.c:139: warning: implicit declaration of function ‘shmctl’
testshm.c:142: warning: incompatible implicit declaration of built-in function ‘exit’
deepfuture@deepfuture-laptop:~/private/mytest$ ./testshmdeepfuture.javeye.com#line 1$deepfuturedeepfuture.javeye.com#line 2$javaeyedeepfuture.javeye.com#line 3$comdeepfuture.javeye.com#line 4$myhaspldeepfuture.javeye.com#line 5$Qdeepfuture.javeye.com#line 6$
退出....
deepfuture@deepfuture-laptop:~/private/mytest$ cat abc.txt
deepfuture
javaeye
com
myhaspl
deepfuture@deepfuture-laptop:~/private/mytest$ C代码
#include <stdio.h>
#include <unistd.h>
#include <linux/types.h>
#include <linux/shm.h>
#include <linux/sem.h>
#include <linux/ipc.h>  #define MAXS  (1024+1)
#define BUFFERSIZE  200
#define SEMID 251//信号标志
#define FILENAME "abc.txt"
#define SHMKEY 241//共享内存标志
#define SHMSIZE MAXS//共享内存大小  //程序完成父进程接收键盘输入,子进程存入文件FILENAME。
//myhaspl  int main(void){  char strbuf[MAXS];  char buf[BUFFERSIZE];  int sem_id;  int shm_id;  int pid;  int rc,res;  struct sembuf sem_op;//信号集结构  union semun sem_val;//信号量数值  char cur;  FILE myfile;  char shm_addr;  int line=1;  //建立信号量集,其中只有一个信号量 myhaspl   sem_id=semget(SEMID,1,IPC_CREAT|0600);//SEMID为为正整数,则为公共的;1为信号集的数量;  if (sem_id==-1){  printf("create sem error!\n");  exit(1);      }  //信号量初始化  sem_val.val=0;  rc=semctl(sem_id,0,SETVAL,sem_val);//设置信号量  if (rc==-1){  printf("initlize sem error!\n");  exit(1);      }  //建立共享内存  shm_id=shmget(SHMKEY,SHMSIZE,IPC_CREAT|0600);//参数为:标志,大小,权限  if (shm_id==-1){  printf("create shm error!\n");  exit(1);      }       //attach共享内存。连接共享内存 myhaspl   shm_addr=(char )shmat(shm_id,NULL,0);//返回共享内存地址 myhaspl   if (!shm_addr){  printf("shmat error!\n");  exit(1);      }   //初始化数据  memset(shm_addr,'\0',MAXS);    cur=shm_addr;//当前字符起始地址  //创建进程  pid=fork();  if (pid==-1){  printf("fork error!\n");  exit(1);             }  else if(pid==0){//子进程,接受键盘输入,往共享内存中写字符行 myhaspl   int isend=0;//是否结束输入  printf("\ndeepfuture.javeye.com#line %d$",line); //自定义键盘输入时使用的SHELL外观     while((!isend)&&fgets(buf,BUFFERSIZE,stdin)!=NULL){//从shell中读入一行    line++;         printf("\ndeepfuture.javeye.com#line %d$",line); //自定义键盘输入时使用的SHELL外观     if (buf[0]=='Q'&&strlen(buf)<=2){//单个字符Q表示退出输入  isend++;//退出输入  printf("\n退出....\n");  }  else  {//如果不是退出命令                         //写共享内存 myhaspl                      memcpy(cur,buf,strlen(buf));              cur+=strlen(buf);  }    //写入一行,增加信号  sem_op.sem_num=0;  sem_op.sem_op=1;  sem_op.sem_flg=0;  semop(sem_id,&sem_op,1);//操作信号量,每次+1          }   cur=-1;   exit(0);     }  else{//父进程,从共享内存中读字符行 ,并写入文件    myhaspl          while(1)  {  //读出一行,减少信号  myhaspl   sem_op.sem_num=0;  sem_op.sem_op=-1;  sem_op.sem_flg=0;  semop(sem_id,&sem_op,1);//操作信号量,每次-1     //myhaspl  读共享内存中一行  if ((cur)==-1) break;//输入结束  int i;  for (i=0;cur!='\n';cur++,i++){                 buf[i]=cur;              }     cur++;                    buf[i]='\n';  buf[++i]=0;  //写文件  FILE fp=fopen(FILENAME,"ab");  res=fwrite(buf,strlen(buf),1,fp);//myhaspl  写入一个行,长度为strlen(buf),个数为1            //size_t fwrite(const void ptr,size_t size,size_t nmemb,FILE * stream);  //size为要写入的每个数据的大小(多少字节),nmemb为要写入数据的个数。myhaspl   if (res==-1){     perror("write error on pipe\n");     exit(1);                     }   fclose(fp);    }  wait(&pid);//等待子进程结束,即用户输入完毕  //分离共享进程  if (shmdt(shm_addr)==-1){  printf("shmdt error!\n");                 }  //撤销共享内存,任何进程只要有权限,都可以撤销共享内存,不一定非要创建它的进程  struct shmid_ds shm_desc;  if (shmctl(shm_id,IPC_RMID,&shm_desc)==-1){  printf("shmctl error!\n");  }  exit(0);   }
}  fgets(由文件中读取一字符串)
相关函数 open,fread,fscanf,getc
表头文件 include<stdio.h>
定义函数 har * fgets(char * s,int size,FILE * stream);
函数说明 fgets()用来从参数stream所指的文件内读入字符并存到参数s所指的内存空间,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。
返回值 gets()若成功则返回s指针,返回NULL则表示有错误发生。
范例 #include<stdio.h>
main()
{
char s[150];
fputs(fgets(s,150,stdin),stdout);
}执行 ,输入:Hello world输出:Hello worldfputs(将一指定的字符串写入文件内)
相关函数 fopen,fwrite,fscanf,fputc,putc
表头文件 #include<stdio.h>
定义函数 int fputs(const char * s,FILE * stream);
函数说明 fputs()用来将参数s所指的字符串写入到参数stream所指的文件内。
返回值 若成功则返回写出的字符个数,返回EOF则表示有错误发生。 fgets()存储输入中的换行符,而fputs()也不为输出添加换行符。strtok()用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数delimiters则为分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该字符改为'\0'字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。C/C++中的Split函数是strtok()其函数原型如下:
char * strtok (char * str, const char * delimiters);
函数说明
strtok()用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数delimiters则为分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该字符改为'\0'字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回下一个分割后的字符串指针。
返回值 返回下一个分割后的字符串指针,如果已无从分割则返回NULL。下面到底哪个是数组指针,哪个是指针数组呢:
A)
long *pa[6];
B)
long (*pb)[6];
每次上课问这个问题,总有弄不清楚的。这里需要明白一个符号之间的优先级问题。“[]”的优先级比“*”要高。pa 先与“[]”结合,构成一个数组的定义,数组名为pa,long *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10 个指向long 类型数据的指针,即指针数组。至于pb ,“()”的优先级比“[]”高,“*”号和pb 构成一个指针的定义,指针变量名为pb,long 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。pb 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针。下面程序完成一个简单的单机投票系统:1. 1.dat与2.dat存放了2个投票的相关内容,投票内容可以依次增多,按数字增序排列。1.dat:4您最喜欢的语言javascriptpythonC++java22.dat:4您最喜欢的操作系统windowsubuntufreebsdSolaris12.投票程序每次运行后都会读取上次投票的结果,并保存本次投票结果,结果保存为csv文件。3.候选人及相关数据保存在下面2个结构中tphsr.h:
#ifndef TPHSR_H_INCLUDED#define TPHSR_H_INCLUDED\//候选人结构struct tp_hsr{int id;char name[10];//候选人int  sel_count;//候选人选票};typedef struct tp_hsr TpHsr;struct tp_hsr_info{TpHsr *tphsr;//候选人明细int hsrcount;//候选人总数char outfn[200];//候选人导出文件名char xzinfo[200];//选举内容int sel_max;//最大候选人};typedef struct tp_hsr_info TpHsrInfo;#endif // TPHSR_H_INCLUDED其它代码如下:tp.h:
#ifndef TP_H_INCLUDED#define TP_H_INCLUDED#include <string.h>#include <conio.h>#include "tphsr.h"#define PASSWD_LEN 100//密码最大长度#define HSR_MAXLEN 100//候选人模板每行长度#define TMPL_FL_PATH "template/"#define FDCOUNT 2void showbegin(){system("cls");printf("   *     ***               *                        \n");printf("                                    *   ****             *  \n");printf("       *    ****                                  **\n");printf(" *                    *    *****                *   \n");printf("          *****  *              *      **    **     * \n");printf("                           ****                            *\n");printf("   * **   ***        *                    *   **\n");printf("                           *    ***   ** ***    \n");printf("     *   *****                                     *  \n");printf("                         *     ***       *          \n");printf("                                                 *      \n");printf("        *  *     *   *****                            \n");printf("             \n投 好 庄 严  一 票\n  ");printf("      #     #######            #      #####             #               \n");printf("   #  #      #   #          #  #     #  #  #         #  #      #####    \n");printf("  #    #     #   #         #    #    #  # #         #    #       #      \n");printf(" #      #  #########      #      #    # # #        #      #   #  #      \n");printf("    #        #   #           #          #             #       #  ###    \n");printf("   #   #     #   #          #   #    #######         #   #    #  #      \n");printf("   #   #    #    #          #   #       #            #   #    #  #      \n");printf("   #### #   #    #          #### #      #            #### #   #######   \n");}TpHsrInfo read_hsr_template(char templ_fn){//读取候选人模板文件FILE *hsrfp;int hsrcount=0;char strline[HSR_MAXLEN];char myfilename[200]="";char outfn[200]="";char *xz_info;strcat(myfilename,TMPL_FL_PATH);strcat(myfilename,templ_fn);if((hsrfp = fopen(myfilename,"rt")) == NULL){return NULL;}//取得候选人总数//第一行为候选人总数fgets(strline,HSR_MAXLEN,hsrfp);hsrcount=atoi(strline);//取得选举内容//第二行为选举内容fgets(strline,HSR_MAXLEN,hsrfp);xz_info=strline;TpHsrInfo myhsrinfo=(TpHsrInfo)malloc(sizeof(TpHsrInfo));TpHsr myhsr=malloc(sizeof(TpHsr)hsrcount);myhsrinfo->tphsr=myhsr;myhsrinfo->hsrcount=hsrcount;strncpy(myhsrinfo->xzinfo,xz_info,strlen(xz_info)-1);myhsrinfo->xzinfo[strlen(xz_info)-1]='\0';strcat(outfn,myhsrinfo->xzinfo);strcat(outfn,".csv");strcpy(myhsrinfo->outfn,outfn);int i=0;while (!feof(hsrfp)){fgets(strline,HSR_MAXLEN,hsrfp);  //读取一行strline[strlen(strline)-1]='\0';myhsrinfo->tphsr[i].id=i+1;strcpy(myhsrinfo->tphsr[i].name,strline);myhsrinfo->tphsr[i].sel_count=0;i++;if (i>=hsrcount) break;}fgets(strline,HSR_MAXLEN,hsrfp);myhsrinfo->sel_max=atoi(strline);fclose(hsrfp);return myhsrinfo;}TpHsrInfo load_hsr(char templ_fn ){//读文件FILE *hsrin_fp;int hsrcount=0;int i=0;const char *csvflag=",";char * p;char strline[HSR_MAXLEN+10];int sel_ct=0;char* sel_ctstr[5];TpHsrInfo *tphsrinfo=read_hsr_template(templ_fn);if(tphsrinfo==NULL){return NULL;}if((hsrin_fp = fopen(tphsrinfo->outfn,"rt")) == NULL){return tphsrinfo;}while (!feof(hsrin_fp)){fgets(strline,HSR_MAXLEN+10,hsrin_fp);p = strtok (strline,csvflag);p = strtok(NULL,csvflag);if (!p) break;strcpy(sel_ctstr,p);sel_ct=atoi(sel_ctstr);tphsrinfo->tphsr[i].sel_count=sel_ct;i++;}fclose(hsrin_fp);return tphsrinfo;}void save_hsr(TpHsrInfo *tphsrinfo){//写文件FILE *hsrout_fp;int hsrcount=0;char linestr[300]={0};int i=0;char sel_ctstr[5]="";if((hsrout_fp = fopen(tphsrinfo->outfn,"wt")) == NULL){printf("%s创建错误!",tphsrinfo->outfn);return NULL;}for(i=0; i<tphsrinfo->hsrcount;i++){strcpy(linestr,tphsrinfo->tphsr[i].name);strcat(linestr," ,");sprintf(sel_ctstr,"%d",tphsrinfo->tphsr[i].sel_count);strcat(linestr,sel_ctstr);strcat(linestr,"\n");fputs(linestr,hsrout_fp);}fclose(hsrout_fp);}int select_hsr(TpHsrInfo *tphsrinfo){//显示候选人int i=0;int xz=0;int hsrsel_max=tphsrinfo->sel_max;int now_selhsr_ct=1;system("cls");printf("-------%s-------\n",tphsrinfo->xzinfo);for(i=0; i<tphsrinfo->hsrcount;i++){printf("%d-",tphsrinfo->tphsr[i].id);printf(tphsrinfo->tphsr[i].name);printf("  票数:%d",tphsrinfo->tphsr[i].sel_count);printf("\t");if ((i+1)%FDCOUNT==0) printf("\n");}printf("请输入编号(输入0表示弃权):");scanf("%d",&xz);while (1){if (xz<0 || xz>tphsrinfo->hsrcount){printf("-------%s-------\n",tphsrinfo->xzinfo);for(i=0; i<tphsrinfo->hsrcount;i++){printf("%d-",tphsrinfo->tphsr[i].id);printf(tphsrinfo->tphsr[i].name);printf("  票数:%d",tphsrinfo->tphsr[i].sel_count);printf("\t");if ((i+1)%FDCOUNT==0) printf("\n");}i=0;printf("请输入编号:");scanf("%d",&xz);}else if (xz==0) {printf("您弃权了!");return 0;}else {printf("您选择:%d-%s",tphsrinfo->tphsr[xz-1].id,tphsrinfo->tphsr[xz-1].name);tphsrinfo->tphsr[xz-1].sel_count++;now_selhsr_ct++;if (now_selhsr_ct<=hsrsel_max) {xz=-1;continue;}return 1;}}}void showtip(){printf("\n每位候选人均有一个编码,输入选中的编码后,按回车键即表示投票!\n按任意键开始投票\n");getch();}int passwd_check(){//密码检测,成功返回1,否则返回0showbegin();int i;char mypass[100];char accept[]="gxds"; //正确登录密码printf("投票选举系统\n");printf("请输入密码:");char pswd;for(i=0; i<PASSWD_LEN-1; i++){pswd=getch();if (pswd==0x0d) break;else mypass[i]=pswd;printf("*");}mypass[i]='\0';if (strcmp(mypass,accept)==0){printf("\n密码正确!下面开始投票!\n");return 1;}else{printf("\n密码错误!按任意键退出程序!\n");getch();return 0;}}#endif // TP_H_INCLUDEDMain.c//投票软件-单机版//纯C,请使用code::blocks打开工程,并编译#include <stdio.h>#include "tp.h"#define TPL_MAX 20int main(int argc,char *argv[]){int is_pass=passwd_check();TpHsrInfo *tphsrinfo[TPL_MAX];int  now_jx=0;char nowjxfn[20]="";int  max_jx=0;while(1){if (is_pass) {sprintf (nowjxfn,"%d",now_jx+1);strcat(nowjxfn,".dat");tphsrinfo[now_jx]=load_hsr(nowjxfn);if (tphsrinfo[now_jx]==NULL) {max_jx=now_jx;break;}showbegin();showtip();select_hsr(tphsrinfo[now_jx]);now_jx++;}else return 0;}now_jx=0;for (now_jx=0;now_jx<max_jx;now_jx++){save_hsr(tphsrinfo[now_jx]);free(tphsrinfo[now_jx]->tphsr);free(tphsrinfo[now_jx]);}return 0;}

C指针原理(45)-LINUX应用相关推荐

  1. 【操作系统原理及Linux实践】 四cpu调度scheduling

    课程: 操作系统原理及Linux实践 cpu调度 调度算法 先来先服务算法(FCFS) Round robin 时间片轮转 最短作业优先 优先级调度算法

  2. Objective-C中,ARC下的 strong和weak指针原理解释

    Objective-C中,ARC下的 strong和weak指针原理解释 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是& ...

  3. 实验9Linux共享内存通信,操作系统原理与Linux实践教程(卓越工程师培养计划系列教材)...

    导语 由申丰山和王黎明共同编著的<操作系统原理与Linux实践教程(卓越工程师培养计划系列教材)>一书理论与实践并重,全面.系统地阐述了操作系统的重要概念和原理,深入.细致地剖析了操作系统 ...

  4. iOS arc weak指针原理

    iOS arc weak指针原理 ARC 都帮我们做了什么? weak是什么? weak是怎么实现的? 1. weak原理简介 2. weak简单测试 3. weak原理分析 3.1 weak指针帮我 ...

  5. linux系统管理设计ppt,操作系统原理与Linux实例设计--第二章.ppt

    操作系统原理与Linux实例设计--第二章.ppt 2.5.4 实时系统与实时任务调度 实时系统与实时任务 实时系统:能及时响应外部请求,并作出反应的系统. 是一个相对的概念. 是否周期执行来划分: ...

  6. 越来越多的岗位需要DPDK,那从DPDK该如何提升网络底层效率丨网络原理丨Linux服务器开发丨后端开发丨网络底层原理

    越来越多的岗位需要dpdk,那从dpdk该如何提升网络底层效率 1. dpdk线程模型 2. kni与数据接收处理流程 3. 手把手代码实现 视频讲解如下,点击观看: 越来越多的岗位需要DPDK,那从 ...

  7. linux系统基本命令实验原理,《操作系统原理与Linux》实验一 Linux基本命令.doc

    <操作系统原理与Linux>实验报告 实验名称:实验一 Linux基本命令的使用 实验日期: 2011年11月1日 班 级:B09513 学 号:20094051311 姓 名:王晓珍 计 ...

  8. C指针原理(30)-C语言-LINUX/UNIX环境下调试

    file 文件名 在gdb中载入某可执行文件 break 设置断点 支持如下形式: break 行号: break 函数名称: break 行号/函数名称 if 条件 info 查看和可执行程序相关的 ...

  9. linux c编译原理,C指针原理教程之编译原理-小型计算器实现

    1.打开cygwin,进入home目录,home目录在WINDOWS系统的cygwin安装目录映射为home目录. 2.首先,在home目录中新建文件夹,在文件夹中放置如下内容的test1.l /*统 ...

最新文章

  1. 黄河科技学院计算机补考好过吗,学生吐槽:重修费每学分240元不该收 黄河科技学院回应:收费合理...
  2. 【嵌入式】C语言高级编程-可变参数宏(12)
  3. J .U.C 中的原子操作类
  4. 彻底卸载WinStdup
  5. MAVEN创建并打包web项目
  6. 会议季Mic Drop:您不应该错过的13场Java演讲
  7. global全局变量
  8. 【华为云技术分享】ARMv8-A存储模型概述(1)
  9. Javascript加号的作用、数据类型、输入用户的输入第四课
  10. 如何在不卸载的情况下暂时禁用Tuxera NTFS
  11. NSArray遍历和修改崩溃
  12. 简单几何(线段相交) POJ 2653 Pick-up sticks
  13. MyBatis3与Spring3的整合配置(初级篇)
  14. Flash互动网站设计学习-Flash发展历史
  15. DO,DTO,VO,POJO, Java 中的各种 O(bject)
  16. 计算机网络设置无法保存,win10系统启用网络发现无法保存的解决步骤
  17. 利用Python进行股票交易分析(一):量化交易策略——买点与卖点的量化
  18. java对接企业微信
  19. java开源图像处理ku_我是这么设计高性能海量数(ku)据(zi)查询系统的(一)
  20. java域名校验_域名规则校验Java版本

热门文章

  1. 主键primary key和唯一索引unique index
  2. UVALive - 7270 Osu! Master
  3. JAVA的WebService规范JAX-WS
  4. (转)NSString to string(支持中文)
  5. hdu 2136 筛法求素数
  6. 各种框架实现了经典的 todo 应用
  7. Python 各种运行错误(如:SyntaxError :invalid syntax)
  8. oracle建job
  9. Tensorflow官方文档中文版——第一章
  10. Scala, Groovy, Clojure, Jython, JRuby and Java ----我们的工作语言