1.
2.
3.
4.
5.
Signals
Mutex (MUTual EXclusion)
Semaphores
Shared memory
Memory mapped files
6.
7.
8.
9.
10.
Cmd1’s stdout becomes
Cmd2’s stdin.
one direction only
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
Pipes via pipe()
(child writing to parent) int main ( int argc, char* argv[] ) { int fd[2] , nbytes; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
Pipes via pipe()
(child writing to parent) int main ( int argc, char* argv[] ) { int fd[2], nbytes; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
if ( (childpid = fork()) == -1 ) { perror( "fork" ); exit( 1 );
}
}
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> int main ( int argc, char* argv[] ) {
Pipes via pipe()
(child writing to parent) int fd[2], nbytes; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 );
} if (childpid == 0) { //child process closes input side of pipe, & writes close( fd[0] );
/* Send "string" through the output side of pipe */
} write( fd[1], string, (strlen(string)+1) );
} else { //parent process closes output side of pipe, & reads close( fd[1] );
/* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer ); return 0;
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
Pipes via pipe()
(child writing to parent) int main ( int argc, char* argv[] ) { int fd[2], nbytes; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
} if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 );
} if (childpid == 0) { //child process closes input side of pipe, & writes close( fd[0] );
/* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) );
} else { //parent process closes output side of pipe, & reads close( fd[1] );
/* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer );
} return 0;
This is child writing to parent.
How can we change it to be parent to child?
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
Pipes via pipe()
(parent writing to child) int main ( int argc, char* argv[] ) { int fd[2], nbytes; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
if ((childpid = fork()) == -1) { perror( "fork" ); exit( 1 );
} if (childpid != 0) { //parent process closes input side of pipe, & writes close( fd[0] );
/* Send "string" through the output side of pipe */
} write( fd[1], string, (strlen(string)+1) );
} else { //child process closes output side of pipe, & reads close( fd[1] );
/* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer );
} return 0;
That was easy!
►
►
sort
►
}
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#define MAXSTRS 5 int main ( int argc, char* argv[] ) {
FILE* pipe_fp;
Pipes via popen()
(pipes to/from processes) char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" };
/* Create one way pipeline with call to popen() */ if ( ( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 );
Can be “w” or “r”.
}
/* Processing loop */
Any valid shell command.
for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp );
}
/* Close the pipe */ pclose( pipe_fp ); return 0;
}
// Excerpt from "Linux Programmer's Guide - Chapter 6."
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#define MAXSTRS 5 int main ( int argc, char* argv[] ) {
FILE* pipe_fp;
Pipes via popen()
(pipes to/from processes) char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" };
/* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 );
}
/* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp );
}
/* Close the pipe */ pclose( pipe_fp ); return 0;
}
// Excerpt from "Linux Programmer's Guide - Chapter 6"
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#define MAXSTRS 5
Pipes via popen() int main ( int argc, char* argv[] ) {
FILE* pipe_fp; char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" };
/* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror( "popen" ); exit( 1 );
}
/* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); fputc( '\n', pipe_fp );
}
/* Close the pipe */ pclose( pipe_fp ); return 0;
How would I modify this to obtain the sorted information?
}
// Excerpt from "Linux Programmer's Guide - Chapter 6"
// (C)opyright 1994-1995, Scott Burkett
#include <stdio.h>
#define MAXSTRS 5 int main ( int argc, char* argv[] ) {
FILE* pipe_fp;
Pipes via popen() char* strings[ MAXSTRS ] = { "echo", "bravo", "alpha", "charlie", "delta" };
/* Create one way pipeline with call to popen() */ if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) { perror( "popen" ); exit( 1 );
}
/* Processing loop */ fputc( '\n', pipe_fp );
}
/* Close the pipe */ pclose( pipe_fp ); return 0;
Any valid shell command.
for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs( strings[cntr], pipe_fp ); How would I modify this to have obtain the sorted information?
This works, but is junk.dat unique?
Named pipes
►
Named pipes
Use mkfifo command. (What is a FIFO?)
Example
► mkfifo mypipe
► ls –l mypipe
rw------1 ggrevera ggrevera 0 Oct 5 21:30 mypipe
► ls –l > mypipe
Hangs! Why?
Ctrl-c
► ls –l > mypipe &
► cat < mypipe
Doesn’t hang! Why?
execlp( "sort", "sort", "-n", NULL ); #include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h> perror( "exec failed." ); //should never get here!
exit( -1 );
} else { //in parent process close( fd[0] ); //close unused side of pipe int main ( int argc, char* argv[] ) { int fd[ 2 ]; pipe( fd ); //fd[0] is opened for reading (input side);
// fd[1] is opened for writing (output side).
pid_t childpid = fork(); assert( childpid != -1 ); if (childpid == 0) { //in child process close( fd[1] ); //MUST close unused side of pipe close( 0 ); //close child's current, default stdin dup( fd[0] ); //duplicate input side of pipe to stdin
//create child process
//execlp( "cat", "cat", NULL );
//execlp( "sort", "sort", NULL );
//write info to pipe char buff[ 256 ]; for (int i=0; i<=10; i++) { sprintf( buff, "%d \n", i ); write( fd[1], buff, strlen(buff) );
}
} close( fd[1] ); //indicates that we are done int status; wait( &status ); //wait for child to finish
} puts( "done." ); return 0; parent’s fd[1] ----> child’s stdin
Named pipes
►
Named pipes
Use mkfifo command. (What is a FIFO?)
Example
► mkfifo mypipe
► ls –l mypipe
rw------1 ggrevera ggrevera 0 Oct 5 21:30 mypipe
► ls –l > mypipe
Hangs! Why?
Because it waits for the reader.
Ctrl-c
► ls –l > mypipe &
► cat < mypipe
Doesn’t hang! Why?
Because the reader executes.
Output on next slide.
►
► ls –l > mypipe & cat < mypipe total 106412
-rwx-----1 ggrevera ggrevera 14215 Oct 5 20:45 a.out
drwx-----5 ggrevera ggrevera 4096 Feb 3 2006 csc4025 drwx-----4 ggrevera ggrevera 4096 Oct 3 09:59 csc4035
-rw------1 ggrevera ggrevera 194560 Sep 6 12:52 csc4035.tar
-rw------1 ggrevera ggrevera 891 Dec 4 2005 dir.cpp
.
.
.
-rw------1 ggrevera ggrevera 283 Oct 5 20:44 sig.cpp
[1]+ Done ls -l >mypipe
Why did this finish? Because the reader reads everything.
►
►
►
►
CreatePipe
Creates an anonymous pipe.
CreateNamedPipe
Creates an instance of a named pipe and returns a handle for subsequent pipe operations. A client process connects to a named pipe by using the CreateFile or CallNamedPipe function.
CallNamedPipe
Connects to a message-type pipe, writes to and reads from the pipe, and then closes the pipe.
TransactNamedPipe
Combines the functions that write a message to and read a message from the specified named pipe into a single network operation.
►
1.
socket()
creates an endpoint for communication and returns a descriptor
2.
connect()
attempts to make a connection to another socket
3.
call read() and/or write()
similar to an ordinary file
Grand list of standard port numbers: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
►
►
►
►
►
//----------------------------------------------------------------------
//----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
Sockets – client-side
(writes a message and reads a response)
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
//---------------------------------------------------------------------static void error ( char* msg ) { perror( msg ); exit( 0 );
}
//---------------------------------------------------------------------int main ( int argc, char* argv[] ) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 );
}
//get port number from command line int portno = atoi( argv[2] );
...
//create an endpoint for communication int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket" );
.
.
.
Sockets – client-side
//get host name from command line struct hostent* server = gethostbyname( argv[1] ); if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); exit( 0 );
}
.
.
.
struct sockaddr_in serv_addr; memset( &serv_addr, sizeof(serv_addr), 0 ); serv_addr.sin_family = AF_INET; memcpy( &serv_addr.sin_addr.s_addr, server->h_addr, server->h_length ); serv_addr.sin_port = htons( portno ); if ( connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ) < 0) error( "ERROR connecting" );
Mention memset and memcpy.
.
.
.
Sockets – client-side printf( "Please enter the message: " ); char buffer[256]; memset( buffer, sizeof(buffer), 0 ); fgets( buffer, sizeof(buffer)-1, stdin );
//fgets includes \n, so we'll remove it (if necessary) if (strlen(buffer) > 0 && buffer[strlen(buffer)-1] == '\n') buffer[ strlen(buffer)-1 ] = 0; int n = write( sockfd, buffer, strlen(buffer)+1 ); //+1 to include \0 if (n < 0) error( "ERROR writing to socket" ); memset( buffer, sizeof(buffer), 0 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error( "ERROR reading from socket" ); printf( "response: %s \n", buffer ); return 0;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// g++ -O2 -o client.exe client.cpp -lsocket -lnsl
//----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
//---------------------------------------------------------------------static void error ( char* msg ) { perror( msg ); exit( 0 );
}
//---------------------------------------------------------------------int main ( int argc, char* argv[] ) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 );
}
//get port number from command line int portno = atoi( argv[2] );
//create an endpoint for communication int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket" );
//get host name from command line struct hostent* server = gethostbyname( argv[1] ); if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); exit( 0 );
} struct sockaddr_in serv_addr; memset( &serv_addr, sizeof(serv_addr), 0 ); serv_addr.sin_family = AF_INET; memcpy( &serv_addr.sin_addr.s_addr, server->h_addr, server->h_length ); serv_addr.sin_port = htons( portno ); if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) error( "ERROR connecting" ); printf( "Please enter the message: " ); char buffer[256]; memset( buffer, sizeof(buffer), 0 ); fgets( buffer, sizeof(buffer)-1, stdin );
//fgets includes \n, so we'll remove it (if necessary) if (strlen(buffer) > 0 && buffer[strlen(buffer)-1] == '\n') buffer[ strlen(buffer)-1 ] = 0; int n = write( sockfd, buffer, strlen(buffer)+1 ); //+1 to include \0 if (n < 0) error( "ERROR writing to socket" ); memset( buffer, sizeof(buffer), 0 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error( "ERROR reading from socket" ); printf( "%s \n", buffer ); return 0;
}
//----------------------------------------------------------------------
Sockets – client-side
(complete code)
Steps:
1.
socket()
creates an endpoint for communication and returns a descriptor
2.
bind()
this is called "assigning a name to a socket" when a socket is created with socket, it exists in a name space (address family) but has no name assigned
3.
listen()
To accept connections, a socket is first created with socket(), a willingness to accept incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are accepted with accept().
4.
repeat forever:
1.
accept()
2.
fork() a child process that performs reads and/or writes as per ordinary file.
►
1.
extracts the first connection request on the queue of pending connections,
2.
creates a new connected socket with mostly the same properties as s,
3.
and allocates a new file descriptor for the socket, which is returned.
►
►
/**
* \file server2.cpp
* \author george j. grevera
* \brief A simple server in the internet domain using TCP. Runs on
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
Sockets – server-side
* polaris (but not on scott).
* To compile: g++ -o server2.exe server2.cpp -lsocket
*/
#include <assert.h> static const int Port = 8090; static const bool Verbose = true;
//---------------------------------------------------------------------int main ( int argc, char* argv[] ) {
…
//create an endpoint for communication if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 );
…
//assign a name to the socket struct sockaddr_in serv_addr;
Sockets – server-side memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family
= AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port
= htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 );
…
Sockets – server-side
…
…
//a willingness to accept incoming connections and a queue
// limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); assert( ret != -1 );
…
} for ( ; ; ) {
//extract the first connection request on the queue of
// pending connections, create a new connected socket with
// mostly the same properties as s, and allocate a new file
// descriptor for the socket, which is returned
Sockets – server-side if (Verbose) puts( "parent: accept()" ); struct sockaddr_in cli_addr; socklen_t clilen = sizeof( cli_addr ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); if (Verbose) puts( "child: begin after fork()" ); close( sockfd ); if (Verbose) puts( "parent: fork()" ); int pid = fork(); if (pid==0) {
<child process code here> char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) );
} close( newsockfd ); //back in parent if (Verbose) puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); return 0;
}
//---------------------------------------------------------------------if (Verbose) { printf( "child: here is the message: %s \n", buffer ); puts( "child: write()" );
} char* msg = "I got your message."; n = write( newsockfd, msg, strlen(msg)+1 ); //+1 to include \0 assert( n != -1 ); close( newsockfd ); if (Verbose) puts( "child: end" ); exit( 0 ); //end child
/**
* \file server2.cpp
* \author george j. grevera
* \brief A simple server in the internet domain using TCP. Runs on
* polaris (but not on scott).
* To compile: g++ -o server2.exe server2.cpp -lsocket
*/
#include <assert.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h> static const int Port = 8090; static const bool Verbose = true;
//---------------------------------------------------------------------int main ( int argc, char* argv[] ) {
//create an endpoint for communication if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 );
//assign a name to the socket struct sockaddr_in serv_addr; memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family
= AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port
= htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 );
//a willingness to accept incoming connections and a queue
// limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); assert( ret != -1 ); for ( ; ; ) {
//extract the first connection request on the queue of
// pending connections, create a new connected socket with
// mostly the same properties as s, and allocate a new file
// descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" ); struct sockaddr_in cli_addr; socklen_t clilen = sizeof( cli_addr ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); if (Verbose) puts( "parent: fork()" ); int pid = fork(); if (pid==0) { if (Verbose) puts( "child: begin after fork()" ); close( sockfd ); char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) ); if (Verbose) puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); if (Verbose) { printf( "child: here is the message: %s \n", buffer ); puts( "child: write()" );
} char* msg = "I got your message."; n = write( newsockfd, msg, strlen(msg)+1 ); //+1 to include \0 assert( n != -1 );
} close( newsockfd ); if (Verbose) puts( "child: end" ); exit( 0 );
} close( newsockfd ); return 0;
}
//----------------------------------------------------------------------
Sockets – server-side
(complete code)
►
./server2.exe
Waits for a message from the client, and then responds.
►
./client.exe brunel 8090
Prompts for a message, sends message to server, and then outputs response message from server.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
►
MSGMAX (Linux) defines the max length of a message
(~8K).
►
Define your message(s).
You may define many different messages of different lengths.
struct myMessage { long mtype;
…
};
//message type
//body of message (you decide)
► msgget - begin accessing (and create if necessary) a message queue int msgget ( key_t key, int msgflg );
► msgsnd - send (enqueue) a message int msgsnd ( int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg );
► msgrcv - receive (dequeue) a message ssize_t msgrcv ( int msqid, struct msgbuf* msgp, size_t msgsz, long msgtyp, int msgflg );
► msgctl - misc. message queue control
//file: m.h
//declare the message structure typedef struct { enum { mTypeA, mTypeB, mTypeC }; long mtype; char mtext[ 256 ];
} message_buf;
#define KEY 1234
//file: mtx.cpp
fprintf( stderr, "msgget: msgget succeeded: msqid = %d \n", msqid );
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// We'll send message type B message_buf sbuf; sbuf.mtype = sbuf.mTypeB; strcpy( sbuf.mtext, "Did you get this?" );
//size_t buf_length = strlen(sbuf.mtext) + 1 ; size_t buf_length = sizeof( message_buf );
#include "m.h" int main ( int argc, char* argv[] ) {
// Get the message queue id for the "name" 1234, which was created by
// the server.
key_t key = KEY; int msgflg = IPC_CREAT | 0666; fprintf( stderr, "\nmsgget: Calling msgget(%#lx,%#o)
\n", key, msgflg ); int msqid; if ((msqid = msgget(key, msgflg)) < 0) { perror( "msgget" ); exit( 1 );
}
// Send a message.
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
} printf( "%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length ); perror( "msgsnd" ); exit( 1 ); printf( "Message: \"%s\" Sent \n", sbuf.mtext );
} return 0;
//file mrx.cpp
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
// Receive an answer of message type B.
message_buf rbuf; if (msgrcv(msqid, &rbuf, sizeof(rbuf), 0, 0) < 0)
{ perror( "msgrcv" ); exit( 1 );
}
#include "m.h" int main ( int argc, char* argv[] ) {
// Get the message queue id for the
"name" KEY, which was created by
// the server.
int msqid = msgget( KEY, 0666 ); if (msqid < 0) { perror( "msgget" ); exit( 1 );
}
}
// Print the answer.
printf( "%d %s \n", rbuf.mtype, rbuf.mtext ); exit( 0 );
►
Call MQOpenQueue to open the queue with send access.
►
Call MQSendMessage to send the message.
►
The MQReceiveMessage function allows you to read messages . When reading messages, you can either peek at (not removing them) or retrieve the messages (removing them) in the queue. Messages can be read either synchronously, asynchronously, or through a transaction.
►
Call MQCloseQueue to close the opened queue and free resources.
►
Creates queue (if necessary, so run first).
Queues up one message.
►
Dequeues a message (waits, otherwise).
►
A collection of procedures, variables, and data structures that are all grouped together in a special kind of module or package.
Only one process can be active in a monitor at any instant.
►
“The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements.”
- from http://download.oracle.com/javase/tutorial/essential/co ncurrency/syncmeth.html
►
“Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The
API specification often refers to this entity simply as a "monitor.")”
- from http://download.oracle.com/javase/tutorial/essential/co ncurrency/locksync.html
1.
2.
►
►
To make a method synchronized, simply add the synchronized keyword to its declaration: public class SynchronizedCounter { private int c = 0; public synchronized void increment ( ) public synchronized void decrement ( ) public synchronized int value ( )
{ c++; }
{ c--; }
{ return c; }
}
If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
1.
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
2.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object.
This guarantees that changes to the state of the object are visible to all threads.
- from http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
►
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns.
The lock release occurs even if the return was caused by an uncaught exception.
- from http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html
►
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object.
►
In this case, the thread acquires the intrinsic lock for the
Class object associated with the class.
►
Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
- from http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html
public void addName ( String name )
{ synchronized (this) { lastName = name; nameCount++;
} nameList.add( name );
}
Single lock taken out on this entire object
(instance).
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1 ( ) {
} synchronized (lock1) {
} c1++; Locks taken out on two different objects for finer control.
public void inc2 ( ) { synchronized (lock2) { c2++;
}
}
}
►
►