diff --git a/c/ServerNBTHR/ClientSideProc.c b/c/ServerNBTHR/ClientSideProc.c new file mode 100644 index 0000000..8ae9448 --- /dev/null +++ b/c/ServerNBTHR/ClientSideProc.c @@ -0,0 +1,36 @@ +/* +* ClientSideProc.c +*/ + +#include /* for memset */ +#include "square.h" +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + CLIENT *cl; + struct square_in in; + struct square_out out; + if (argc != 3) { + printf("Usage : client \n"); + exit(1); + } + cl = clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, "tcp"); + if (cl == NULL) { + clnt_perror(cl, "call failed"); + exit(1); + } + in.arg1 = atol(argv[2]); + if (squareproc_2(&in, &out, cl) != RPC_SUCCESS) { + printf("%s\n", clnt_perror(cl, argv[1])); + exit(1); + } + printf("result: %ld\n", out.res1); + exit(0); +} diff --git a/c/ServerNBTHR/ServerNBTHR.c b/c/ServerNBTHR/ServerNBTHR.c new file mode 100644 index 0000000..de6d02f --- /dev/null +++ b/c/ServerNBTHR/ServerNBTHR.c @@ -0,0 +1,293 @@ +/* +* ServerNBTHR.c +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NUM_THREADS 512 + +pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER; + +void +die(const char *func, int err) +{ + fprintf(stderr,"%s: %s\n",func, strerror(err)); + abort(); +} + +void +bark(const char *func, int err) +{ + fprintf(stderr,"%s: %s\n",func, strerror(err)); +} +/* + Описание поцедуры ведущего потока , которая возвращает +дескрипторов пассивного сокета, привязанного к адресу +сервера. +*/ +int +getServerSocket(unsigned short int port) +{ + int listenSocket; + struct sockaddr_in listenSockaddr; + + if((listenSocket=socket(PF_INET,SOCK_STREAM,0))<0) + die("socket()",errno); + memset(&listenSockaddr, 0, sizeof(listenSockaddr)); + listenSockaddr.sin_family = PF_INET; + listenSockaddr.sin_port = htons(port); + listenSockaddr.sin_addr.s_addr = INADDR_ANY; + + if(bind(listenSocket,(struct sockaddr*)&listenSockaddr, + sizeof(listenSockaddr)) < 0) + die("bind()",errno); + + if(listen(listenSocket,5)<0) + die("listen()",errno); + + return listenSocket; +} + +/* + Описание процедуры выполняемой всеми ведомыми потоками +*/ + + +void * +serv_request(void *data) +{ +struct connection_cb +{ + int dataSocket; + char data[256]; + int dataSent; + int dataToSend; + int isReading; + struct connection_cb *next; +}; + +struct connection_cb *connections = NULL; + +int listenSocket = (int)data; + if(fcntl(listenSocket,F_SETFL,O_NONBLOCK)<0) + die("fcntl()",errno); + + while(1) + { + fd_set readFdSet; + fd_set writeFdSet; + struct connection_cb *currentConn, **currentConnPtr, *tempConn; + int maxFdNum; + + FD_ZERO(&readFdSet); + FD_ZERO(&writeFdSet); + + /* + Добавление дескриптора к множеству readFdSet + */ + FD_SET(listenSocket,&readFdSet); + maxFdNum = listenSocket; + + for(currentConn = connections;currentConn!=NULL;currentConn = + currentConn->next) + { + if(currentConn->isReading) + FD_SET(currentConn->dataSocket,&readFdSet); + else + FD_SET(currentConn->dataSocket,&writeFdSet); + maxFdNum = currentConn->dataSocket > maxFdNum ?currentConn- + >dataSocket : maxFdNum; + } + /* + Получение множества дескрипторов сокетов для обработки + */ + if(select(maxFdNum+1,&readFdSet,&writeFdSet,NULL,NULL) < 0) + { + if(errno == EINTR) + continue; + die("select()",errno); + } + + currentConnPtr=&connections; + + while(*currentConnPtr!=NULL) + { + + /* + Проверка принадлежности дескриптора + (*currentConnPtr)->dataSocket к множеству readFdSet + */ + + if((*currentConnPtr)->isReading && + FD_ISSET((*currentConnPtr)->dataSocket,&readFdSet)) + { + int result = recv((*currentConnPtr)->dataSocket, (*currentConnPtr)->data, + sizeof((*currentConnPtr)->data),0); + + if(result < 0) + { + if(errno!=EINTR && errno!=EAGAIN && errno!=EWOULDBLOCK) + { + bark("recv()",errno); + close((*currentConnPtr)->dataSocket); + tempConn = *currentConnPtr; + *currentConnPtr = (*currentConnPtr)->next; + free(tempConn); + continue; + } + } + else + if(result==0) + { + close((*currentConnPtr)->dataSocket); + tempConn = *currentConnPtr; + *currentConnPtr = (*currentConnPtr)->next; + free(tempConn); + continue; + } + else + { + (*currentConnPtr)->dataToSend = result; + (*currentConnPtr)->dataSent = 0; + (*currentConnPtr)->isReading = 0; + printf("Recieving as Slave Thread id = '%d' \n",pthread_self()); + } + } + else + /* + Проверка принадлежности дескриптора + (*currentConnPtr)->dataSocket к множеству writedFdSet + */ + if(FD_ISSET((*currentConnPtr)->dataSocket,&writeFdSet)) + { + int result = send((*currentConnPtr)->dataSocket, + (*currentConnPtr)->data+(*currentConnPtr)->dataSent, + (*currentConnPtr) ->dataToSend-(*currentConnPtr)->dataSent, 0); + + if(result < 0) + { + if(errno!=EINTR && errno!=EAGAIN) + { + bark("write()",errno); + close((*currentConnPtr)->dataSocket); + tempConn = *currentConnPtr; + *currentConnPtr = (*currentConnPtr)->next; + free(tempConn); + continue; + } + } + else + { + (*currentConnPtr)->dataSent +=result; + + if((*currentConnPtr)->dataSent >= (*currentConnPtr)->dataToSend) + (*currentConnPtr)->isReading = 1; + } + } + + currentConnPtr = &((*currentConnPtr)->next); + printf("Sending as Slave Thread id = '%d' \n",pthread_self()); + } + /* + Проверка принадлежности дескриптора listenSocket + к множеству readFdSet,т.е. необходимости обработать + вызов connect( ) от нового клиента. + */ + if(FD_ISSET(listenSocket,&readFdSet)) + { + + while(1) + { + + /* + Вызовы pthread_mutex_lock, pthread_mutex_unlock + Не нужны в среде Linux + */ + pthread_mutex_lock(&request_mutex); + int result = accept(listenSocket,(struct sockaddr*)NULL,NULL); + pthread_mutex_unlock(&request_mutex); + if(result < 0) + { + if(errno==EAGAIN || errno == EWOULDBLOCK) + break; + die("accept()",errno); + } + else + { + *currentConnPtr = malloc(sizeof(struct connection_cb)); + if(*currentConnPtr==NULL) + die("malloc()",0); + + if(fcntl(result,F_SETFL,O_NONBLOCK)<0) + die("fcntl()",errno); + + (*currentConnPtr)->dataSocket = result; + (*currentConnPtr)->isReading = 1; + (*currentConnPtr)->next = 0; + currentConnPtr = &((*currentConnPtr)->next); + printf("Accepting as Master Thread id = '%d' \n",pthread_self()); + } + } + } + } +} +int +main(int argc,char *argv[]) +{ +int k; +int descSock; +char *service="1500"; +switch(argc) { +case 1: + break; +case 2: + service = argv[1]; + break; +default: + printf ("Usage: ./ServerBNTH [port]\n"); + exit(1); +} + +size_t stacksize; +pthread_t p_thread[NUM_THREADS]; + +/* + Установка размера стека для ведомых потоков +*/ + +pthread_attr_t attr; + pthread_attr_init(&attr); + stacksize = 500000; + pthread_attr_setstacksize (&attr, stacksize); + pthread_attr_getstacksize (&attr, &stacksize); + +/* + Получение значения дескриптора пассивного сокета +*/ + + descSock = getServerSocket(atoi(service)); + +/* + Запуск ведомых потоков +*/ + +for(k=0; k +#include +#include +#include +#include +#include +#include + +int request=0; + +bool_t squareproc_2_svc(square_in *inp,square_out *outp,struct svc_req *rqstp) +{ + printf("Thread id = '%ld' started, arg = %d\n",pthread_self(),inp->arg1); + /* + Имитация работы процедуры , выполняемой потоками сервера + */ + sleep(5); + outp->res1=inp->arg1*inp->arg1; + printf("Thread id = '%ld' is done %d \n",pthread_self(),outp->res1); + return(TRUE); +} +int square_prog_2_freeresult(SVCXPRT *transp,xdrproc_t xdr_result, caddr_t result) +{ + xdr_free(xdr_result,result); + return(1); +} diff --git a/c/ServerNBTHR/run.sh b/c/ServerNBTHR/run.sh new file mode 100755 index 0000000..21ab9d2 --- /dev/null +++ b/c/ServerNBTHR/run.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +rpcgen -a -M square.x + +gcc -o ServerSQUARE ServerSideProc.c square_svc.c square_xdr.c -lpthread -lnsl + +gcc -o ClientSQUARE ClientSideProc.c square_clnt.c square_xdr.c -lprthread -lnsl diff --git a/c/ServerNBTHR/square.h b/c/ServerNBTHR/square.h new file mode 100644 index 0000000..794e35d --- /dev/null +++ b/c/ServerNBTHR/square.h @@ -0,0 +1,11 @@ +struct square_in { + long arg1; +}; +struct square_out { + long res1; +}; +program SQUARE_PROG { + version SQUARE_VERS { + square_out SQUAREPROC(square_in) = 1; + } = 2 ; +} = 0x31230000; diff --git a/c/ServerNBTHR/square_client.c b/c/ServerNBTHR/square_client.c new file mode 100644 index 0000000..dcf8ef9 --- /dev/null +++ b/c/ServerNBTHR/square_client.c @@ -0,0 +1,48 @@ +/* + * This is sample code generated by rpcgen. + * These are only templates and you can use them + * as a guideline for developing your own functions. + */ + +#include "square.h" + + +void +square_prog_2(char *host) +{ + CLIENT *clnt; + enum clnt_stat retval_1; + square_out result_1; + square_in squareproc_2_arg; + +#ifndef DEBUG + clnt = clnt_create (host, SQUARE_PROG, SQUARE_VERS, "udp"); + if (clnt == NULL) { + clnt_pcreateerror (host); + exit (1); + } +#endif /* DEBUG */ + + retval_1 = squareproc_2(&squareproc_2_arg, &result_1, clnt); + if (retval_1 != RPC_SUCCESS) { + clnt_perror (clnt, "call failed"); + } +#ifndef DEBUG + clnt_destroy (clnt); +#endif /* DEBUG */ +} + + +int +main (int argc, char *argv[]) +{ + char *host; + + if (argc < 2) { + printf ("usage: %s server_host\n", argv[0]); + exit (1); + } + host = argv[1]; + square_prog_2 (host); +exit (0); +} diff --git a/c/ServerNBTHR/square_server.c b/c/ServerNBTHR/square_server.c new file mode 100644 index 0000000..a618f20 --- /dev/null +++ b/c/ServerNBTHR/square_server.c @@ -0,0 +1,31 @@ +/* + * This is sample code generated by rpcgen. + * These are only templates and you can use them + * as a guideline for developing your own functions. + */ + +#include "square.h" + +bool_t +squareproc_2_svc(square_in *argp, square_out *result, struct svc_req *rqstp) +{ + bool_t retval; + + /* + * insert server code here + */ + + return retval; +} + +int +square_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) +{ + xdr_free (xdr_result, result); + + /* + * Insert additional freeing code here, if needed + */ + + return 1; +} diff --git a/c/ServerNBTHR/square_svc.c b/c/ServerNBTHR/square_svc.c new file mode 100644 index 0000000..a6e1b17 --- /dev/null +++ b/c/ServerNBTHR/square_svc.c @@ -0,0 +1,166 @@ +/* square_svc.c + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "square.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +pthread_t p_thread; +pthread_attr_t attr; + +/* + + Процедура выполняемая потоком + + */ + +void * +serv_request(void *data) +{ +struct thr_data +{ +struct svc_req *rqstp; +SVCXPRT *transp; +} *ptr_data; + +{ + + union { + square_in squareproc_2_arg; + } argument; + union { + square_out squareproc_2_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + +/* + + Распаковка данных , переданных в процедуру при запуске потока. + +*/ + +ptr_data = (struct thr_data *)data; +struct svc_req *rqstp = ptr_data->rqstp; +register SVCXPRT *transp = ptr_data->transp; + + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case SQUAREPROC: + _xdr_argument = (xdrproc_t) xdr_square_in; + _xdr_result = (xdrproc_t) xdr_square_out; + local = (bool_t (*) (char *, void *, struct svc_req *))squareproc_2_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + + /* + + Стандартный вызов функции сервера. + Данные для вызова уже приведены к стандарту. + + */ + + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) + { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!square_prog_2_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + return; +} +} + +/* + +Принципиально измененный код square_prog_2 , стартующей теперь +новый поток для каждого инициированного клиентом вызова +процедуры на удаленном сервере + +*/ + +static void +square_prog_2(struct svc_req *rqstp, register SVCXPRT *transp) +{ +struct data_str +{ +struct svc_req *rqstp; +SVCXPRT *transp; +} *data_ptr =(struct data_str*)malloc(sizeof(struct data_str); + +{ + +/* + Упаковка данных в структуру для передачи ссылки на нее, + как параметра запускаемому потоку +*/ + +data_ptr->rqstp = rqstp; +data_ptr->transp = transp; +pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); +pthread_create(&p_thread,&attr,serv_request,(void *)data_ptr); + } +} + +int +main (int argc, char **argv) +{ + register SVCXPRT *transp; + + pmap_unset (SQUARE_PROG, SQUARE_VERS); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create udp service."); + exit(1); + } + if (!svc_register(transp, SQUARE_PROG, SQUARE_VERS, square_prog_2, IPPROTO_UDP)) { + fprintf (stderr, "%s", "unable to register (SQUARE_PROG, SQUARE_VERS, udp)."); + exit(1); + } + + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create tcp service."); + exit(1); + } + if (!svc_register(transp, SQUARE_PROG, SQUARE_VERS, square_prog_2, IPPROTO_TCP)) { + fprintf (stderr, "%s", "unable to register (SQUARE_PROG, SQUARE_VERS, tcp)."); + exit(1); + } + + svc_run (); + fprintf (stderr, "%s", "svc_run returned"); + exit (1); + /* NOTREACHED */ +} diff --git a/c/sockets/echo-client.c b/c/echo_server/echo-client.c similarity index 100% rename from c/sockets/echo-client.c rename to c/echo_server/echo-client.c diff --git a/c/sockets/echo-server.c b/c/echo_server/echo-server.c similarity index 100% rename from c/sockets/echo-server.c rename to c/echo_server/echo-server.c diff --git a/c/sockets/int2ip.c b/c/echo_server/int2ip.c similarity index 100% rename from c/sockets/int2ip.c rename to c/echo_server/int2ip.c diff --git a/c/sockets/ip2int.c b/c/echo_server/ip2int.c similarity index 100% rename from c/sockets/ip2int.c rename to c/echo_server/ip2int.c diff --git a/c/sockets/sock1.c b/c/echo_server/sock1.c similarity index 100% rename from c/sockets/sock1.c rename to c/echo_server/sock1.c diff --git a/c/sockets/tmp1.c b/c/echo_server/tmp1.c similarity index 100% rename from c/sockets/tmp1.c rename to c/echo_server/tmp1.c diff --git a/c/masync_server/echo-client.c b/c/masync_server/echo-client.c new file mode 100644 index 0000000..5093ce6 --- /dev/null +++ b/c/masync_server/echo-client.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#include +#include +#include + +unsigned int ip2int(const char * s) { + int ip[4]; + sscanf(s,"%d.%d.%d.%d",ip,ip+1,ip+2,ip+3); + return ip[0]<<24|ip[1]<<16|ip[2]<<8|ip[3]; +} + +int sendall(int s, char *buf, int len, int flags) +{ + int total = 0; + int n; + + while(total < len) + { + n = send(s, buf+total, len-total, flags); + if(n == -1) { break; } + total += n; + } + + return (n==-1 ? -1 : total); +} + +char message[] = "Hello there!\n"; +char buf[sizeof(message)]; + +int main() +{ + int sock; + struct sockaddr_in addr; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) + { + perror("socket"); + exit(1); + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(3425); // или любой другой порт... + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // (ip2int("192.168.2.1")); + if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + perror("connect"); + exit(2); + } + + send(sock, message, sizeof(message), 0); + recv(sock, buf, sizeof(message), 0); + + printf("%s\n",buf); + close(sock); + + return 0; +} diff --git a/c/masync_server/echo-server.c b/c/masync_server/echo-server.c new file mode 100644 index 0000000..d68930b --- /dev/null +++ b/c/masync_server/echo-server.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include +#include +#include + +static const char * int2ip(unsigned int ip) { + static char s[16]; + sprintf(s,"%d.%d.%d.%d",ip>>24,ip<<8>>24,ip<<16>>24,ip<<24>>24); + return s; +} + +int main() +{ + int sock, listener; + struct sockaddr_in addr; + char buf[1024]; + int bytes_read; + + listener = socket(AF_INET, SOCK_STREAM, 0); + if(listener < 0) + { + perror("socket"); + exit(1); + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(3425); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + perror("bind"); + exit(2); + } + + listen(listener, 1); + //~ printf("%X\n",addr.sin_addr.s_addr); + while(1) + { + socklen_t n = sizeof(struct sockaddr); + sock = accept(listener, (struct sockaddr *)&addr, &n); + printf("incoming request from %s\n",int2ip(ntohl(addr.sin_addr.s_addr))); + //~ printf("%X\n",addr.sin_addr.s_addr); + if(sock < 0) + { + perror("accept"); + exit(3); + } + + while(1) + { + bytes_read = recv(sock, buf, 1024, 0); + if(bytes_read <= 0) break; + send(sock, buf, bytes_read, 0); + printf("%s", buf); + } + + close(sock); + } + + return 0; +} diff --git a/c/masync_server/int2ip.c b/c/masync_server/int2ip.c new file mode 100644 index 0000000..eccdb22 --- /dev/null +++ b/c/masync_server/int2ip.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +static const char * int2ip(unsigned int ip) { + static char s[16]; + sprintf(s,"%d.%d.%d.%d",ip>>24,ip<<8>>24,ip<<16>>24,ip<<24>>24); + return s; +} + +int main(int argc, char * argv[]) { + if(argc < 2) { + perror("need hex ip address"); + exit(1); + } + + unsigned int ip = 0; + sscanf(argv[1],"%X",&ip); + + printf("%s\n",int2ip(ip)); + + return 0; +} diff --git a/c/masync_server/ip2int.c b/c/masync_server/ip2int.c new file mode 100644 index 0000000..7b44472 --- /dev/null +++ b/c/masync_server/ip2int.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +unsigned int ip2int(const char * s) { + int ip[4]; + sscanf(s,"%d.%d.%d.%d",ip,ip+1,ip+2,ip+3); + return ip[0]<<24|ip[1]<<16|ip[2]<<8|ip[3]; +} + +int main(int argc, char * argv[]) { + if(argc < 2) { + perror("need ip address string"); + exit(1); + } + + printf("%X\n",ip2int(argv[1])); + + return 0; +} diff --git a/c/masync_server/sock1.c b/c/masync_server/sock1.c new file mode 100644 index 0000000..27c255c --- /dev/null +++ b/c/masync_server/sock1.c @@ -0,0 +1,67 @@ +#include +#include +#include + +//~ domain = AF_UNIX, AF_INET, AF_INET6, AF_IPX +//~ type = SOCK_STREAM, SOCK_DGRAM, SOCK_RAW +//~ int socket(int domain, int type, int protocol); + +//~ struct sockaddr { + //~ unsigned short sa_family; // Семейство адресов, AF_xxx + //~ char sa_data[14]; // 14 байтов для хранения адреса +//~ }; +//~ struct sockaddr_in { + //~ short int sin_family; // Семейство адресов + //~ unsigned short int sin_port; // Номер порта + //~ struct in_addr sin_addr; // IP-адрес + //~ unsigned char sin_zero[8]; // "Дополнение" до размера структуры sockaddr +//~ }; +//~ struct in_addr { + //~ unsigned long s_addr; +//~ }; +//~ htons, htonl, ntohs, ntohl +//~ int bind(int sockfd, struct sockaddr *addr, int addrlen); + +//~ int listen(int sockfd, int backlog); +//~ int accept(int sockfd, void *addr, int *addrlen); + +// клиент +//~ int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); + +//~ int send(int sockfd, const void *msg, int len, int flags); + +// отправка буфера целиком +//~ int sendall(int s, char *buf, int len, int flags) +//~ { + //~ int total = 0; + //~ int n; +//~ + //~ while(total < len) + //~ { + //~ n = send(s, buf+total, len-total, flags); + //~ if(n == -1) { break; } + //~ total += n; + //~ } +//~ + //~ return (n==-1 ? -1 : total); +//~ } + +//~ int recv(int sockfd, void *buf, int len, int flags); + +// закрытие соединения +//~ int close(int fd); + +// запрет передачи 0 - чтения, 1 - записи, 2 - и того, и др. +//~ int shutdown(int sockfd, int how); + + +int main(int argc, char * argv[]) +{ + struct a + { + char aaa[256]; + }; + + printf("%lu\n", sizeof(struct a)); + return 0; +} diff --git a/c/masync_server/tmp1.c b/c/masync_server/tmp1.c new file mode 100644 index 0000000..e41de65 --- /dev/null +++ b/c/masync_server/tmp1.c @@ -0,0 +1,25 @@ +#include + +void f() +{ + int c = 0; + printf("c=%lu\n",(unsigned long)&c); +} + + +int main(int argc, char * argv[]) { + //~ printf("%lu\n", sizeof(long)); + + int a = 0; + + int pid = fork(); + printf("pid=%d\n",pid); + printf("a=%lu\n",(unsigned long)&a); + + int b = 0; + printf("b=%lu\n",(unsigned long)&b); + + f(); + + return 0; +}